@@ -154,7 +154,11 @@ final class HashMap[K, +V] private[immutable] (private[immutable] val rootNode:
154
154
}
155
155
}
156
156
157
- override def transform [W ](f : (K , V ) => W ) = new HashMap (rootNode.transform(f), cachedJavaKeySetHashCode)
157
+ override def transform [W ](f : (K , V ) => W ) = {
158
+ val transformed = rootNode.transform(f)
159
+ if (transformed eq rootNode) this .asInstanceOf [HashMap [K , W ]]
160
+ else new HashMap (transformed, cachedJavaKeySetHashCode)
161
+ }
158
162
159
163
override def filterImpl (pred : ((K , V )) => Boolean , flipped : Boolean ): HashMap [K , V ] = {
160
164
// This method has been preemptively overridden in order to ensure that an optimizing implementation may be included
@@ -652,23 +656,41 @@ private final class BitmapIndexedMapNode[K, +V](
652
656
}
653
657
654
658
override def transform [W ](f : (K , V ) => W ): BitmapIndexedMapNode [K , W ] = {
655
- val newContent = content.clone()
659
+ var newContent : Array [ Any ] = null
656
660
val _payloadArity = payloadArity
657
661
val _nodeArity = nodeArity
658
- val newContentLength = newContent .length
662
+ val newContentLength = content .length
659
663
var i = 0
660
664
while (i < _payloadArity) {
661
- newContent(TupleLength * i + 1 ) = f(getKey(i), getValue(i))
665
+ val key = getKey(i)
666
+ val value = getValue(i)
667
+ val newValue = f(key, value)
668
+ if (newContent eq null ) {
669
+ if (newValue.asInstanceOf [AnyRef ] ne value.asInstanceOf [AnyRef ]) {
670
+ newContent = content.clone()
671
+ newContent(TupleLength * i + 1 ) = newValue
672
+ }
673
+ } else {
674
+ newContent(TupleLength * i + 1 ) = newValue
675
+ }
662
676
i += 1
663
677
}
664
678
665
679
var j = 0
666
680
while (j < _nodeArity) {
667
- newContent(newContentLength - j - 1 ) = getNode(j).transform(f)
681
+ val node = getNode(j)
682
+ val newNode = node.transform(f)
683
+ if (newContent eq null ) {
684
+ if (newNode ne node) {
685
+ newContent = content.clone()
686
+ newContent(newContentLength - j - 1 ) = newNode
687
+ }
688
+ } else
689
+ newContent(newContentLength - j - 1 ) = newNode
668
690
j += 1
669
691
}
670
-
671
- new BitmapIndexedMapNode [K , W ](dataMap, nodeMap, newContent, originalHashes, size)
692
+ if (newContent eq null ) this . asInstanceOf [ BitmapIndexedMapNode [ K , W ]]
693
+ else new BitmapIndexedMapNode [K , W ](dataMap, nodeMap, newContent, originalHashes, size)
672
694
}
673
695
674
696
override def equals (that : Any ): Boolean =
@@ -818,13 +840,18 @@ private final class HashCollisionMapNode[K, +V ](
818
840
def foreach [U ](f : ((K , V )) => U ): Unit = content.foreach(f)
819
841
820
842
override def transform [W ](f : (K , V ) => W ): HashCollisionMapNode [K , W ] = {
821
- val newContent = Vector .newBuilder[(K , W )]
843
+ var newContent = Vector .newBuilder[(K , W )]
822
844
val contentIter = content.iterator
845
+ // true if any values have been transformed to a different value via `f`
846
+ var anyChanges = false
823
847
while (contentIter.hasNext) {
824
848
val (k, v) = contentIter.next()
825
- newContent.addOne((k, f(k, v)))
849
+ val newValue = f(k, v)
850
+ newContent.addOne((k, newValue))
851
+ anyChanges ||= (v.asInstanceOf [AnyRef ] ne newValue.asInstanceOf [AnyRef ])
826
852
}
827
- new HashCollisionMapNode (originalHash, hash, newContent.result())
853
+ if (anyChanges) new HashCollisionMapNode (originalHash, hash, newContent.result())
854
+ else this .asInstanceOf [HashCollisionMapNode [K , W ]]
828
855
}
829
856
830
857
override def equals (that : Any ): Boolean =
0 commit comments