在Scala 2.7.7中,添加null时会直接得到null指针:
scala> val s = new scala.collection.mutable.HashSet[String]
s: scala.collection.mutable.HashSet[String] = Set()
scala> s += null
java.lang.NullPointerException
at scala.collection.mutable.FlatHashTable$class.elemHashCode(FlatHashTable.scala:144)
at scala.collection.mutable.HashSet.elemHashCode(HashSet.scala:31)
at scala.collection.mutable.FlatHashTable$class.addEntry(FlatHashTable.scala:66)
at scala.collection.mutable.HashSet.addEntry(HashSet.scala:31)
at scala.collection.mutable.HashSet.$plus$eq(HashSet.s...
使用scala2.8.0.RC7,情况就不再是这样了。然而,作为
Randall has observed
,行为也不完全一致:
scala> import scala.collection.mutable.HashSet
import scala.collection.mutable.HashSet
scala> val s = new HashSet[String]
s: scala.collection.mutable.HashSet[String] = Set()
scala> s += null
res0: s.type = Set()
scala> s += null
res1: s.type = Set()
scala> s.size
res2: Int = 2
scala> s.head
java.util.NoSuchElementException: next on empty iterator
at scala.collection.Iterator$$anon$3.next(Iterator.scala:29)
at scala.collection.Iterator$$anon$3.next(Iterator.scala:27)
at scala.collection.mutable.FlatHashTable$$anon$1.next(FlatHashTable.scala:176)
at scala.collection.IterableLike$class.head(IterableLike.scala:102)
at scala.collection.mutable.HashSet.head(HashSet.scala:38)
at .(:8)
添加条目时的大部分工作都是在中完成的
FlatHashTable
addEntry
调用,如下所示:
/** The actual hash table.
*/
@transient protected var table: Array[AnyRef] = new Array(initialCapacity)
def addEntry(elem: A) : Boolean = {
var h = index(elemHashCode(elem))
var entry = table(h)
while (null != entry) {
if (entry == elem) return false
h = (h + 1) % table.length
entry = table(h)
}
table(h) = elem.asInstanceOf[AnyRef]
tableSize = tableSize + 1
if (tableSize >= threshold) growTable()
true
}
null.asInstanceOf[AnyRef]
只是还给你
null
elemHashCode(elem)
returns zero if the elem is
null
. So in this case, the element with index zero is 'initialized' with
null
(which is the value it already had), but the tableSize is increased. This explains the results that are seen in the REPL.
如果你打电话
head
FlatHashTable
调用,从stacktrace可以看出。具体实施如下:
iterator = new Iterator[A] {
private var i = 0
def hasNext: Boolean = {
while (i < table.length && (null == table(i))) i += 1
i < table.length
}
def next(): A =
if (hasNext) { i += 1; table(i - 1).asInstanceOf[A] }
else Iterator.empty.next
}
hasNext
next
将调用Iterator.empty.next,这将引发异常。
编辑
因为我找不到这张票,我
added it
.