diff options
Diffstat (limited to 'src')
4 files changed, 35 insertions, 38 deletions
diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala index f8dd9c1c79..4ffcc111cc 100644 --- a/src/library/scala/collection/MapLike.scala +++ b/src/library/scala/collection/MapLike.scala @@ -165,7 +165,7 @@ self => def + (elem: A): Set[A] = (Set[A]() ++ this + elem).asInstanceOf[Set[A]] // !!! concrete overrides abstract problem def - (elem: A): Set[A] = (Set[A]() ++ this - elem).asInstanceOf[Set[A]] // !!! concrete overrides abstract problem override def size = self.size - override def foreach[C](f: A => C) = for ((k, v) <- self) f(k) + override def foreach[C](f: A => C) = self.keysIterator foreach f } /** Creates an iterator for all keys. @@ -197,7 +197,7 @@ self => protected class DefaultValuesIterable extends Iterable[B] { def iterator = valuesIterator override def size = self.size - override def foreach[C](f: B => C) = for ((k, v) <- self) f(v) + override def foreach[C](f: B => C) = self.valuesIterator foreach f } /** Creates an iterator for all values in this map. diff --git a/src/library/scala/collection/mutable/DefaultEntry.scala b/src/library/scala/collection/mutable/DefaultEntry.scala index 66ca375f13..95ac98efe7 100644 --- a/src/library/scala/collection/mutable/DefaultEntry.scala +++ b/src/library/scala/collection/mutable/DefaultEntry.scala @@ -6,13 +6,9 @@ ** |/ ** \* */ - - package scala.collection package mutable - - /** Class used internally for default map model. * @since 2.3 */ diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index b082fc2770..98ece514f7 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -6,18 +6,12 @@ ** |/ ** \* */ - - package scala.collection package mutable import generic._ - - import scala.collection.parallel.mutable.ParHashMap - - /** This class implements mutable maps using a hashtable. * * @since 1 @@ -112,16 +106,16 @@ extends Map[A, B] /* Override to avoid tuple allocation */ override def keysIterator: Iterator[A] = new Iterator[A] { - val iter = entriesIterator + val iter = entriesIterator def hasNext = iter.hasNext - def next() = iter.next.key + def next() = iter.next.key } /* Override to avoid tuple allocation */ override def valuesIterator: Iterator[B] = new Iterator[B] { - val iter = entriesIterator + val iter = entriesIterator def hasNext = iter.hasNext - def next() = iter.next.value + def next() = iter.next.value } /** Toggles whether a size map is used to track hash map statistics. diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala index 0f6fde0260..004b112253 100644 --- a/src/library/scala/collection/mutable/HashTable.scala +++ b/src/library/scala/collection/mutable/HashTable.scala @@ -54,6 +54,14 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU protected def initialSize: Int = HashTable.initialSize + private def lastPopulatedIndex = { + var idx = table.length - 1 + while (table(idx) == null && idx > 0) + idx -= 1 + + idx + } + /** * Initializes the collection from the input stream. `f` will be called for each key/value pair * read from the input stream in the order determined by the stream. This is useful for @@ -156,38 +164,37 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU */ protected def entriesIterator: Iterator[Entry] = new Iterator[Entry] { val iterTable = table - var idx = table.length - 1 - var es = iterTable(idx).asInstanceOf[Entry] - scan() + var idx = lastPopulatedIndex + var es = iterTable(idx) + def hasNext = es != null def next() = { val res = es es = es.next - scan() - res - } - def scan() { while (es == null && idx > 0) { idx = idx - 1 - es = iterTable(idx).asInstanceOf[Entry] + es = iterTable(idx) } + res.asInstanceOf[Entry] } } - /* - * We should implement this as a primitive operation over the underlying array, but it can - * cause a behaviour change in edge cases where: - * - Someone modifies a map during iteration - * - The insertion point is close to the iteration point. - * - * The reason this happens is that the iterator prefetches the following element before - * returning from next (to simplify the implementation of hasNext) while the natural - * implementation of foreach does not. - * - * It should be mentioned that modifying a map during iteration leads to unpredictable - * results with either implementation. - */ - protected final def foreachEntry[C](f: Entry => C) { entriesIterator.foreach(f) } + /** Avoid iterator for a 2x faster traversal. */ + protected final def foreachEntry[C](f: Entry => C) { + val iterTable = table + var idx = lastPopulatedIndex + var es = iterTable(idx) + + while (es != null) { + f(es.asInstanceOf[Entry]) + es = es.next + + while (es == null && idx > 0) { + idx -= 1 + es = iterTable(idx) + } + } + } /** An iterator returning all entries */ @deprecated("use entriesIterator instead", "2.8.0") |