Skip to content

Commit a826497

Browse files
committed
Optimize HashMap#transform
Fix typo in HashMap#transform
1 parent 714d5ec commit a826497

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

library/src/scala/collection/immutable/ChampHashMap.scala

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ final class HashMap[K, +V] private[immutable] (private[immutable] val rootNode:
154154
}
155155
}
156156

157+
override def transform[W](f: (K, V) => W) = new HashMap(rootNode.transform(f), cachedJavaKeySetHashCode)
158+
157159
override def filterImpl(pred: ((K, V)) => Boolean, flipped: Boolean): HashMap[K, V] = {
158160
// This method has been preemptively overridden in order to ensure that an optimizing implementation may be included
159161
// in a minor release without breaking binary compatibility.
@@ -173,15 +175,6 @@ final class HashMap[K, +V] private[immutable] (private[immutable] val rootNode:
173175
super.removeAll(keys)
174176
}
175177

176-
override def transform[W](f: (K, V) => W): HashMap[K, W] = {
177-
// This method has been preemptively overridden in order to ensure that an optimizing implementation may be included
178-
// in a minor release without breaking binary compatibility.
179-
//
180-
// In particular, `transform` could be optimized to traverse the trie node-by-node, swapping out the values of each
181-
// key with the result of applying `f`.
182-
super.transform(f)
183-
}
184-
185178
override def partition(p: ((K, V)) => Boolean): (HashMap[K, V], HashMap[K, V]) = {
186179
// This method has been preemptively overridden in order to ensure that an optimizing implementation may be included
187180
// in a minor release without breaking binary compatibility.
@@ -255,6 +248,7 @@ final class HashMap[K, +V] private[immutable] (private[immutable] val rootNode:
255248
// checks.
256249
super.span(p)
257250
}
251+
258252
}
259253

260254
private[immutable] object MapNode {
@@ -303,6 +297,8 @@ private[immutable] sealed abstract class MapNode[K, +V] extends Node[MapNode[K,
303297

304298
def foreach[U](f: ((K, V)) => U): Unit
305299

300+
def transform[W](f: (K, V) => W): MapNode[K, W]
301+
306302
def copy(): MapNode[K, V]
307303
}
308304

@@ -655,6 +651,26 @@ private final class BitmapIndexedMapNode[K, +V](
655651
}
656652
}
657653

654+
override def transform[W](f: (K, V) => W): BitmapIndexedMapNode[K, W] = {
655+
val newContent = content.clone()
656+
val _payloadArity = payloadArity
657+
val _nodeArity = nodeArity
658+
val newContentLength = newContent.length
659+
var i = 0
660+
while (i < _payloadArity) {
661+
newContent(TupleLength * i + 1) = f(getKey(i), getValue(i))
662+
i += 1
663+
}
664+
665+
var j = 0
666+
while (j < _nodeArity) {
667+
newContent(newContentLength - j - 1) = getNode(j).transform(f)
668+
j += 1
669+
}
670+
671+
new BitmapIndexedMapNode[K, W](dataMap, nodeMap, newContent, originalHashes, size)
672+
}
673+
658674
override def equals(that: Any): Boolean =
659675
that match {
660676
case node: BitmapIndexedMapNode[K, V] =>
@@ -801,6 +817,16 @@ private final class HashCollisionMapNode[K, +V ](
801817

802818
def foreach[U](f: ((K, V)) => U): Unit = content.foreach(f)
803819

820+
override def transform[W](f: (K, V) => W): HashCollisionMapNode[K, W] = {
821+
val newContent = Vector.newBuilder[(K, W)]
822+
val contentIter = content.iterator
823+
while(contentIter.hasNext) {
824+
val (k, v) = contentIter.next()
825+
newContent.addOne((k, f(k, v)))
826+
}
827+
new HashCollisionMapNode(originalHash, hash, newContent.result())
828+
}
829+
804830
override def equals(that: Any): Boolean =
805831
that match {
806832
case node: HashCollisionMapNode[K, V] =>

0 commit comments

Comments
 (0)