Skip to content

Commit cb81086

Browse files
authored
Merge pull request scala/scala#8630 from hrhino/topic/hashmap-transform
[nomerge] HashMap#transform reuses structure
2 parents 7d73da9 + 70ca7b5 commit cb81086

File tree

1 file changed

+32
-3
lines changed

1 file changed

+32
-3
lines changed

library/src/scala/collection/immutable/HashMap.scala

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,12 @@ sealed class HashMap[A, +B] extends AbstractMap[A, B]
153153
}
154154
override def values: scala.collection.Iterable[B] = new HashMapValues
155155

156+
override final def transform[W, That](f: (A, B) => W)(implicit bf: CanBuildFrom[HashMap[A, B], (A, W), That]): That =
157+
if ((bf eq Map.canBuildFrom) || (bf eq HashMap.canBuildFrom)) transformImpl(f).asInstanceOf[That]
158+
else super.transform(f)(bf)
156159

160+
/* `transform` specialized to return a HashMap */
161+
protected def transformImpl[W](f: (A, B) => W): HashMap[A, W] = HashMap.empty
157162
}
158163

159164
/** $factoryInfo
@@ -187,10 +192,12 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
187192
}
188193

189194
/** $mapCanBuildFromInfo */
190-
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), HashMap[A, B]] = new MapCanBuildFrom[A, B]
195+
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), HashMap[A, B]] =
196+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (A, B), HashMap[A, B]]]
197+
private val ReusableCBF = new MapCanBuildFrom[Nothing, Nothing]
191198
def empty[A, B]: HashMap[A, B] = EmptyHashMap.asInstanceOf[HashMap[A, B]]
192199

193-
private object EmptyHashMap extends HashMap[Any, Nothing] {
200+
private object EmptyHashMap extends HashMap[Any, Nothing] {
194201
override def head: (Any, Nothing) = throw new NoSuchElementException("Empty Map")
195202
override def tail: HashMap[Any, Nothing] = throw new NoSuchElementException("Empty Map")
196203
}
@@ -268,7 +275,7 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
268275

269276
override def equals(that: Any): Boolean = {
270277
that match {
271-
case hm: HashMap1[_,_] =>
278+
case hm: HashMap1[_, _] =>
272279
(this eq hm) ||
273280
(hm.hash == hash && hm.key == key && hm.value == value)
274281
case _: HashMap[_, _] =>
@@ -277,6 +284,12 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
277284
super.equals(that)
278285
}
279286
}
287+
288+
protected override def transformImpl[W](f: (A, B) => W): HashMap[A, W] = {
289+
val value1 = f(key, value)
290+
if (value1.asInstanceOf[AnyRef] eq value.asInstanceOf[AnyRef]) this.asInstanceOf[HashMap1[A, W]]
291+
else new HashMap1(key, hash, value1, null)
292+
}
280293
}
281294

282295
private[collection] class HashMapCollision1[A, +B](private[collection] val hash: Int, val kvs: ListMap[A, B @uV])
@@ -361,6 +374,9 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
361374
}
362375
}
363376

377+
protected override def transformImpl[W](f: (A, B) => W): HashMap[A, W] = {
378+
new HashMapCollision1[A, W](hash, kvs transform f)
379+
}
364380
}
365381

366382
@deprecatedInheritance("This class will be made final in a future release.", "2.12.2")
@@ -636,6 +652,19 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
636652
}
637653
}
638654

655+
protected override def transformImpl[W](f: (A, B) => W): HashMap[A, W] = {
656+
val elems1 = new Array[HashMap[A, W]](elems.length)
657+
var i = 0
658+
while (i < elems.length) {
659+
val elem = elems(i)
660+
if (elem ne null) {
661+
val elem1 = elem.transformImpl(f)
662+
elems1(i) = elem1
663+
}
664+
i += 1
665+
}
666+
new HashTrieMap[A, W](bitmap, elems1, size)
667+
}
639668
}
640669

641670
/**

0 commit comments

Comments
 (0)