Skip to content

Commit 230d327

Browse files
authored
Merge pull request scala/scala#8467 from rorygraves/mike/2.12_CanBuildFrom
Avoid allocations of reusable CanBuildFroms
2 parents 02fca85 + 2c14985 commit 230d327

30 files changed

+255
-75
lines changed

library/src/scala/Array.scala

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,78 @@ object Array extends FallbackArrayBuilding {
6161
val emptyShortArray = new Array[Short](0)
6262
val emptyObjectArray = new Array[Object](0)
6363

64-
implicit def canBuildFrom[T](implicit t: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] =
64+
implicit def canBuildFrom[T](implicit tag: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] = {
65+
val cls = tag.runtimeClass
66+
(if (cls.isPrimitive) {
67+
cls match {
68+
case java.lang.Integer.TYPE => cbfIntArray
69+
case java.lang.Double.TYPE => cbfDoubleArray
70+
case java.lang.Long.TYPE => cbfLongArray
71+
case java.lang.Float.TYPE => cbfFloatArray
72+
case java.lang.Character.TYPE => cbfCharArray
73+
case java.lang.Byte.TYPE => cbfByteArray
74+
case java.lang.Short.TYPE => cbfShortArray
75+
case java.lang.Boolean.TYPE => cbfBooleanArray
76+
case java.lang.Void.TYPE => cbfUnitArray
77+
}
78+
} else if (cls == ObjectClass) {
79+
cbfObjectArray
80+
} else {
81+
refCBF[T with AnyRef](tag.asInstanceOf[ClassTag[T with AnyRef]])
82+
}).asInstanceOf[CanBuildFrom[Array[_], T, Array[T]]]
83+
}
84+
private[this] val ObjectClass = classOf[Object]
85+
86+
private[this] val cbfBooleanArray = new CanBuildFrom[Array[_], Boolean, Array[Boolean]] {
87+
def apply(from: Array[_]) = new ArrayBuilder.ofBoolean()
88+
def apply() = new ArrayBuilder.ofBoolean()
89+
}
90+
91+
private[this] val cbfByteArray = new CanBuildFrom[Array[_], Byte, Array[Byte]] {
92+
def apply(from: Array[_]) = new ArrayBuilder.ofByte()
93+
def apply() = new ArrayBuilder.ofByte()
94+
}
95+
96+
private[this] val cbfCharArray = new CanBuildFrom[Array[_], Char, Array[Char]] {
97+
def apply(from: Array[_]) = new ArrayBuilder.ofChar()
98+
def apply() = new ArrayBuilder.ofChar()
99+
}
100+
101+
private[this] val cbfDoubleArray = new CanBuildFrom[Array[_], Double, Array[Double]] {
102+
def apply(from: Array[_]) = new ArrayBuilder.ofDouble()
103+
def apply() = new ArrayBuilder.ofDouble()
104+
}
105+
106+
private[this] val cbfFloatArray = new CanBuildFrom[Array[_], Float, Array[Float]] {
107+
def apply(from: Array[_]) = new ArrayBuilder.ofFloat()
108+
def apply() = new ArrayBuilder.ofFloat()
109+
}
110+
111+
private[this] val cbfIntArray = new CanBuildFrom[Array[_], Int, Array[Int]] {
112+
def apply(from: Array[_]) = new ArrayBuilder.ofInt()
113+
def apply() = new ArrayBuilder.ofInt()
114+
}
115+
116+
private[this] val cbfLongArray = new CanBuildFrom[Array[_], Long, Array[Long]] {
117+
def apply(from: Array[_]) = new ArrayBuilder.ofLong()
118+
def apply() = new ArrayBuilder.ofLong()
119+
}
120+
121+
private[this] val cbfShortArray = new CanBuildFrom[Array[_], Short, Array[Short]] {
122+
def apply(from: Array[_]) = new ArrayBuilder.ofShort()
123+
def apply() = new ArrayBuilder.ofShort()
124+
}
125+
126+
private[this] val cbfUnitArray = new CanBuildFrom[Array[_], Unit, Array[Unit]] {
127+
def apply(from: Array[_]) = new ArrayBuilder.ofUnit()
128+
def apply() = new ArrayBuilder.ofUnit()
129+
}
130+
131+
private[this] val cbfObjectArray = refCBF[Object]
132+
private[this] def refCBF[T <: AnyRef](implicit t: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] =
65133
new CanBuildFrom[Array[_], T, Array[T]] {
66-
def apply(from: Array[_]) = ArrayBuilder.make[T]()(t)
67-
def apply() = ArrayBuilder.make[T]()(t)
134+
def apply(from: Array[_]) = new ArrayBuilder.ofRef[T]()(t)
135+
def apply() = new ArrayBuilder.ofRef[T]()(t)
68136
}
69137

70138
/**

library/src/scala/collection/BitSet.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ object BitSet extends BitSetFactory[BitSet] {
3232
def newBuilder = immutable.BitSet.newBuilder
3333

3434
/** $canBuildFromInfo */
35-
implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom
35+
implicit val canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom
3636
}
3737

library/src/scala/collection/GenMap.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,8 @@ object GenMap extends GenMapFactory[GenMap] {
3535
def empty[K, V]: immutable.Map[K, V] = immutable.Map.empty
3636

3737
/** $mapCanBuildFromInfo */
38-
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), GenMap[K, V]] = new MapCanBuildFrom[K, V]
38+
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), GenMap[K, V]] =
39+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (K, V), GenMap[K, V]]]
40+
private[this] val ReusableCBF = new MapCanBuildFrom[Nothing, Nothing]
41+
3942
}

library/src/scala/collection/Map.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ object Map extends MapFactory[Map] {
4545
def empty[K, V]: immutable.Map[K, V] = immutable.Map.empty
4646

4747
/** $mapCanBuildFromInfo */
48-
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V]
48+
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] =
49+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (K, V), Map[K, V]]]
50+
private[this] val ReusableCBF = new MapCanBuildFrom[Nothing, Nothing]
4951

5052
/** An abstract shell used by { mutable, immutable }.Map but not by collection.Map
5153
* because of variance issues.

library/src/scala/collection/Set.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ trait Set[A] extends (A => Boolean)
4444
object Set extends SetFactory[Set] {
4545
def newBuilder[A] = immutable.Set.newBuilder[A]
4646
override def empty[A]: Set[A] = immutable.Set.empty[A]
47-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A]
47+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] =
48+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Set[A]]]
49+
private[this] val ReusableCBF = setCanBuildFrom[Any]
4850
}
4951

5052
/** Explicit instantiation of the `Set` trait to reduce class file size in subclasses. */

library/src/scala/collection/concurrent/TrieMap.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,9 @@ extends scala.collection.concurrent.Map[K, V]
970970
object TrieMap extends MutableMapFactory[TrieMap] {
971971
val inodeupdater = AtomicReferenceFieldUpdater.newUpdater(classOf[INodeBase[_, _]], classOf[MainNode[_, _]], "mainnode")
972972

973-
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), TrieMap[K, V]] = new MapCanBuildFrom[K, V]
973+
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), TrieMap[K, V]] =
974+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (K, V), TrieMap[K, V]]]
975+
private[this] val ReusableCBF = new MapCanBuildFrom[Nothing, Nothing]
974976

975977
def empty[K, V]: TrieMap[K, V] = new TrieMap[K, V]
976978

library/src/scala/collection/immutable/BitSet.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ object BitSet extends BitSetFactory[BitSet] {
8181
}
8282

8383
/** $bitsetCanBuildFrom */
84-
implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom
84+
implicit val canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom
8585

8686
/** A bitset containing all the bits in an array */
8787
def fromBitMask(elems: Array[Long]): BitSet = {

library/src/scala/collection/immutable/HashSet.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,9 @@ sealed class HashSet[A] extends AbstractSet[A]
213213
object HashSet extends ImmutableSetFactory[HashSet] {
214214

215215
/** $setCanBuildFromInfo */
216-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] = setCanBuildFrom[A]
216+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] =
217+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, HashSet[A]]]
218+
private[this] val ReusableCBF = setCanBuildFrom[Any]
217219

218220
private object EmptyHashSet extends HashSet[Any] {
219221
override def head: Any = throw new NoSuchElementException("Empty Set")

library/src/scala/collection/immutable/IntMap.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ package scala
1414
package collection
1515
package immutable
1616

17-
import scala.collection.generic.{ CanBuildFrom, BitOperations }
18-
import scala.collection.mutable.{ Builder, MapBuilder }
17+
import scala.collection.generic.{BitOperations, CanBuildFrom}
18+
import scala.collection.mutable.{Builder, MapBuilder}
1919
import scala.annotation.tailrec
2020

2121
/** Utility class for integer maps.
@@ -50,9 +50,11 @@ import IntMapUtils._
5050
*/
5151
object IntMap {
5252
/** $mapCanBuildFromInfo */
53-
implicit def canBuildFrom[A, B] = new CanBuildFrom[IntMap[A], (Int, B), IntMap[B]] {
54-
def apply(from: IntMap[A]): Builder[(Int, B), IntMap[B]] = apply()
55-
def apply(): Builder[(Int, B), IntMap[B]] = new MapBuilder[Int, B, IntMap[B]](empty[B])
53+
implicit def canBuildFrom[A, B]: CanBuildFrom[IntMap[A], (Int, B), IntMap[B]] =
54+
ReusableCBF.asInstanceOf[CanBuildFrom[IntMap[A], (Int, B), IntMap[B]]]
55+
private val ReusableCBF = new CanBuildFrom[IntMap[Any], (Int, Any), IntMap[Any]] {
56+
def apply(from: IntMap[Any]): Builder[(Int, Any), IntMap[Any]] = apply()
57+
def apply(): Builder[(Int, Any), IntMap[Any]] = new MapBuilder[Int, Any, IntMap[Any]](empty[Any])
5658
}
5759

5860
def empty[T] : IntMap[T] = IntMap.Nil

library/src/scala/collection/immutable/ListMap.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ object ListMap extends ImmutableMapFactory[ListMap] {
3737
* $mapCanBuildFromInfo
3838
*/
3939
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), ListMap[A, B]] =
40-
new MapCanBuildFrom[A, B]
40+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (A, B), ListMap[A, B]]]
41+
private[this] val ReusableCBF = new MapCanBuildFrom[Any, Any]
4142

4243
def empty[A, B]: ListMap[A, B] = EmptyListMap.asInstanceOf[ListMap[A, B]]
4344

library/src/scala/collection/immutable/ListSet.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ object ListSet extends ImmutableSetFactory[ListSet] {
3434
* $setCanBuildFromInfo
3535
*/
3636
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ListSet[A]] =
37-
setCanBuildFrom[A]
37+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, ListSet[A]]]
38+
private[this] val ReusableCBF = setCanBuildFrom[Any]
3839

3940
@SerialVersionUID(5010379588739277132L)
4041
private object EmptyListSet extends ListSet[Any]

library/src/scala/collection/immutable/LongMap.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ import LongMapUtils._
5050
*/
5151
object LongMap {
5252
/** $mapCanBuildFromInfo */
53-
implicit def canBuildFrom[A, B] = new CanBuildFrom[LongMap[A], (Long, B), LongMap[B]] {
54-
def apply(from: LongMap[A]): Builder[(Long, B), LongMap[B]] = apply()
55-
def apply(): Builder[(Long, B), LongMap[B]] = new MapBuilder[Long, B, LongMap[B]](empty[B])
53+
implicit def canBuildFrom[A, B]: CanBuildFrom[LongMap[A], (Long, B), LongMap[B]] =
54+
ReusableCBF.asInstanceOf[CanBuildFrom[LongMap[A], (Long, B), LongMap[B]]]
55+
private[this] val ReusableCBF = new CanBuildFrom[LongMap[Any], (Long, Any), LongMap[Any]] {
56+
def apply(from: LongMap[Any]): Builder[(Long, Any), LongMap[Any]] = apply()
57+
def apply(): Builder[(Long, Any), LongMap[Any]] = new MapBuilder[Long, Any, LongMap[Any]](empty[Any])
5658
}
5759

5860
def empty[T]: LongMap[T] = LongMap.Nil

library/src/scala/collection/immutable/Map.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ trait Map[K, +V] extends Iterable[(K, V)]
8383
object Map extends ImmutableMapFactory[Map] {
8484

8585
/** $mapCanBuildFromInfo */
86-
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V]
86+
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] =
87+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (K, V), Map[K, V]]]
88+
private[this] val ReusableCBF = new MapCanBuildFrom[Nothing, Nothing]
8789

8890
def empty[K, V]: Map[K, V] = EmptyMap.asInstanceOf[Map[K, V]]
8991

library/src/scala/collection/immutable/Set.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ trait Set[A] extends Iterable[A]
6464
*/
6565
object Set extends ImmutableSetFactory[Set] {
6666
/** $setCanBuildFromInfo */
67-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A]
67+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] =
68+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Set[A]]]
69+
private[this] val ReusableCBF = setCanBuildFrom[Any]
6870

6971
/** An optimized representation for immutable empty sets */
7072
@SerialVersionUID(-2443710944435909512L)

library/src/scala/collection/immutable/Stream.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,9 @@ object Stream extends SeqFactory[Stream] {
10871087
*/
10881088
class StreamCanBuildFrom[A] extends GenericCanBuildFrom[A]
10891089

1090-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Stream[A]] = new StreamCanBuildFrom[A]
1090+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Stream[A]] =
1091+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Stream[A]]]
1092+
private[this] val ReusableCBF = new StreamCanBuildFrom[Any]
10911093

10921094
/** Creates a new builder for a stream */
10931095
def newBuilder[A]: Builder[A, Stream[A]] = new StreamBuilder[A]

library/src/scala/collection/immutable/WrappedString.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ final class WrappedString(val self: String) extends AbstractSeq[Char] with Index
5656
* @since 2.8
5757
*/
5858
object WrappedString {
59-
implicit def canBuildFrom: CanBuildFrom[WrappedString, Char, WrappedString] = new CanBuildFrom[WrappedString, Char, WrappedString] {
59+
implicit val canBuildFrom: CanBuildFrom[WrappedString, Char, WrappedString] = new CanBuildFrom[WrappedString, Char, WrappedString] {
6060
def apply(from: WrappedString) = newBuilder
6161
def apply() = newBuilder
6262
}

library/src/scala/collection/mutable/AnyRefMap.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -450,10 +450,11 @@ object AnyRefMap {
450450
private val exceptionDefault = new ExceptionDefault
451451

452452
implicit def canBuildFrom[K <: AnyRef, V, J <: AnyRef, U]: CanBuildFrom[AnyRefMap[K,V], (J, U), AnyRefMap[J,U]] =
453-
new CanBuildFrom[AnyRefMap[K,V], (J, U), AnyRefMap[J,U]] {
454-
def apply(from: AnyRefMap[K,V]): AnyRefMapBuilder[J, U] = apply()
455-
def apply(): AnyRefMapBuilder[J, U] = new AnyRefMapBuilder[J, U]
456-
}
453+
ReusableCBFInstance.asInstanceOf[CanBuildFrom[AnyRefMap[K, V], (J, U), AnyRefMap[J, U]]]
454+
private[this] val ReusableCBFInstance = new CanBuildFrom[AnyRefMap[AnyRef, Any], (AnyRef, Any), AnyRefMap[AnyRef, Any]] {
455+
def apply(from: AnyRefMap[AnyRef, Any]): AnyRefMapBuilder[AnyRef, Any] = apply()
456+
def apply(): AnyRefMapBuilder[AnyRef, Any] = new AnyRefMapBuilder[AnyRef, Any]
457+
}
457458

458459
/** A builder for instances of `AnyRefMap`.
459460
*

library/src/scala/collection/mutable/ArrayBuilder.scala

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,21 @@ object ArrayBuilder {
3737
*/
3838
def make[T: ClassTag](): ArrayBuilder[T] = {
3939
val tag = implicitly[ClassTag[T]]
40-
tag.runtimeClass match {
41-
case java.lang.Byte.TYPE => new ArrayBuilder.ofByte().asInstanceOf[ArrayBuilder[T]]
42-
case java.lang.Short.TYPE => new ArrayBuilder.ofShort().asInstanceOf[ArrayBuilder[T]]
43-
case java.lang.Character.TYPE => new ArrayBuilder.ofChar().asInstanceOf[ArrayBuilder[T]]
44-
case java.lang.Integer.TYPE => new ArrayBuilder.ofInt().asInstanceOf[ArrayBuilder[T]]
45-
case java.lang.Long.TYPE => new ArrayBuilder.ofLong().asInstanceOf[ArrayBuilder[T]]
46-
case java.lang.Float.TYPE => new ArrayBuilder.ofFloat().asInstanceOf[ArrayBuilder[T]]
47-
case java.lang.Double.TYPE => new ArrayBuilder.ofDouble().asInstanceOf[ArrayBuilder[T]]
48-
case java.lang.Boolean.TYPE => new ArrayBuilder.ofBoolean().asInstanceOf[ArrayBuilder[T]]
49-
case java.lang.Void.TYPE => new ArrayBuilder.ofUnit().asInstanceOf[ArrayBuilder[T]]
50-
case _ => new ArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ClassTag[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]]
40+
val cls = tag.runtimeClass
41+
if (cls.isPrimitive) {
42+
cls match {
43+
case java.lang.Integer.TYPE => new ArrayBuilder.ofInt().asInstanceOf[ArrayBuilder[T]]
44+
case java.lang.Double.TYPE => new ArrayBuilder.ofDouble().asInstanceOf[ArrayBuilder[T]]
45+
case java.lang.Long.TYPE => new ArrayBuilder.ofLong().asInstanceOf[ArrayBuilder[T]]
46+
case java.lang.Float.TYPE => new ArrayBuilder.ofFloat().asInstanceOf[ArrayBuilder[T]]
47+
case java.lang.Character.TYPE => new ArrayBuilder.ofChar().asInstanceOf[ArrayBuilder[T]]
48+
case java.lang.Byte.TYPE => new ArrayBuilder.ofByte().asInstanceOf[ArrayBuilder[T]]
49+
case java.lang.Short.TYPE => new ArrayBuilder.ofShort().asInstanceOf[ArrayBuilder[T]]
50+
case java.lang.Boolean.TYPE => new ArrayBuilder.ofBoolean().asInstanceOf[ArrayBuilder[T]]
51+
case java.lang.Void.TYPE => new ArrayBuilder.ofUnit().asInstanceOf[ArrayBuilder[T]]
52+
}
53+
} else {
54+
new ArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ClassTag[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]]
5155
}
5256
}
5357

library/src/scala/collection/mutable/BitSet.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ object BitSet extends BitSetFactory[BitSet] {
193193
def newBuilder: Builder[Int, BitSet] = new GrowingBuilder[Int, BitSet](empty)
194194

195195
/** $bitsetCanBuildFrom */
196-
implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom
196+
implicit val canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom
197197

198198
/** A bitset containing all the bits in an array */
199199
def fromBitMask(elems: Array[Long]): BitSet = {

library/src/scala/collection/mutable/HashMap.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ extends AbstractMap[A, B]
200200
* @define coll mutable hash map
201201
*/
202202
object HashMap extends MutableMapFactory[HashMap] {
203-
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), HashMap[A, B]] = new MapCanBuildFrom[A, B]
203+
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), HashMap[A, B]] =
204+
ReusableCBF.asInstanceOf[MapCanBuildFrom[A, B]]
205+
private[this] val ReusableCBF = new MapCanBuildFrom[Any, Any]
206+
204207
def empty[A, B]: HashMap[A, B] = new HashMap[A, B]
205208
}

library/src/scala/collection/mutable/HashSet.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ extends AbstractSet[A]
104104
* @define coll mutable hash set
105105
*/
106106
object HashSet extends MutableSetFactory[HashSet] {
107-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] = setCanBuildFrom[A]
107+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] =
108+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, HashSet[A]]]
109+
private[this] val ReusableCBF = setCanBuildFrom[Any]
108110
override def empty[A]: HashSet[A] = new HashSet[A]
109111
}
110112

library/src/scala/collection/mutable/LinkedHashMap.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import generic._
2121
* @define coll linked hash map
2222
*/
2323
object LinkedHashMap extends MutableMapFactory[LinkedHashMap] {
24-
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), LinkedHashMap[A, B]] = new MapCanBuildFrom[A, B]
24+
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), LinkedHashMap[A, B]] =
25+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (A, B), LinkedHashMap[A, B]]]
26+
private [this] val ReusableCBF = new MapCanBuildFrom[Any, Any]
2527
def empty[A, B] = new LinkedHashMap[A, B]
2628
}
2729

library/src/scala/collection/mutable/LinkedHashSet.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ class LinkedHashSet[A] extends AbstractSet[A]
135135
* @define coll linked hash set
136136
*/
137137
object LinkedHashSet extends MutableSetFactory[LinkedHashSet] {
138-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, LinkedHashSet[A]] = setCanBuildFrom[A]
138+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, LinkedHashSet[A]] =
139+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, LinkedHashSet[A]]]
140+
private[this] val ReusableCBF = setCanBuildFrom[Any]
139141
override def empty[A]: LinkedHashSet[A] = new LinkedHashSet[A]
140142

141143
/** Class for the linked hash set entry, used internally.

library/src/scala/collection/mutable/LongMap.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -526,9 +526,10 @@ object LongMap {
526526
private val exceptionDefault: Long => Nothing = (k: Long) => throw new NoSuchElementException(k.toString)
527527

528528
implicit def canBuildFrom[V, U]: CanBuildFrom[LongMap[V], (Long, U), LongMap[U]] =
529-
new CanBuildFrom[LongMap[V], (Long, U), LongMap[U]] {
530-
def apply(from: LongMap[V]): LongMapBuilder[U] = apply()
531-
def apply(): LongMapBuilder[U] = new LongMapBuilder[U]
529+
ReusableCBF.asInstanceOf[CanBuildFrom[LongMap[V], (Long, U), LongMap[U]]]
530+
private[this] val ReusableCBF = new CanBuildFrom[LongMap[Any], (Long, Any), LongMap[Any]] {
531+
def apply(from: LongMap[Any]): LongMapBuilder[Any] = apply()
532+
def apply(): LongMapBuilder[Any] = new LongMapBuilder[Any]
532533
}
533534

534535
/** A builder for instances of `LongMap`.

library/src/scala/collection/mutable/Map.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ trait Map[K, V]
5858
*/
5959
object Map extends MutableMapFactory[Map] {
6060
/** $canBuildFromInfo */
61-
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V]
61+
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] =
62+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (K, V), Map[K, V]]]
63+
private[this] val ReusableCBF = new MapCanBuildFrom[Nothing, Nothing]
6264

6365
def empty[K, V]: Map[K, V] = new HashMap[K, V]
6466

library/src/scala/collection/mutable/Set.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ trait Set[A] extends Iterable[A]
4040
* @define Coll `mutable.Set`
4141
*/
4242
object Set extends MutableSetFactory[Set] {
43-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A]
43+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] =
44+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Set[A]]]
45+
private[this] val ReusableCBF = setCanBuildFrom[Any]
4446
override def empty[A]: Set[A] = HashSet.empty[A]
4547
}
4648

0 commit comments

Comments
 (0)