Skip to content

Commit af7d5a3

Browse files
committed
Use java.util.Arrays.copyOf to extend or contract arrays, when the content of the previous array is to be copied into the new Array
Use clone when the array is not changing length Maintain empty Arrays in the Array object, and use them where possible Maintain empty WrappedArrays in WrappedArrays object and use where possible
1 parent 80aa1cd commit af7d5a3

File tree

6 files changed

+117
-78
lines changed

6 files changed

+117
-78
lines changed

library/src/scala/Array.scala

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,23 @@ class FallbackArrayBuilding {
5151
* @since 1.0
5252
*/
5353
object Array extends FallbackArrayBuilding {
54-
val emptyBooleanArray = new Array[Boolean](0)
55-
val emptyByteArray = new Array[Byte](0)
56-
val emptyCharArray = new Array[Char](0)
57-
val emptyDoubleArray = new Array[Double](0)
58-
val emptyFloatArray = new Array[Float](0)
59-
val emptyIntArray = new Array[Int](0)
60-
val emptyLongArray = new Array[Long](0)
61-
val emptyShortArray = new Array[Short](0)
62-
val emptyObjectArray = new Array[Object](0)
54+
private val emptyArrays = new ClassValue[AnyRef] {
55+
override def computeValue(cls: Class[_]): AnyRef =
56+
java.lang.reflect.Array.newInstance(cls, 0)
57+
}
58+
59+
val emptyBooleanArray = empty[Boolean]
60+
val emptyByteArray = empty[Byte]
61+
val emptyCharArray = empty[Char]
62+
val emptyDoubleArray = empty[Double]
63+
val emptyFloatArray = empty[Float]
64+
val emptyIntArray = empty[Int]
65+
val emptyLongArray = empty[Long]
66+
val emptyShortArray = empty[Short]
67+
68+
private[scala] //this is only private because of binary compatability
69+
val emptyUnitArray = empty[scala.runtime.BoxedUnit].asInstanceOf[Array[Unit]]
70+
val emptyObjectArray = empty[Object]
6371

6472
implicit def canBuildFrom[T](implicit tag: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] = {
6573
val cls = tag.runtimeClass
@@ -179,8 +187,10 @@ object Array extends FallbackArrayBuilding {
179187
}
180188

181189
/** Returns an array of length 0 */
182-
def empty[T: ClassTag]: Array[T] = new Array[T](0)
183-
190+
def empty[T: ClassTag]: Array[T] = {
191+
val cls = implicitly[ClassTag[T]].runtimeClass.asInstanceOf[Class[T]]
192+
emptyArrays.get(cls).asInstanceOf[Array[T]]
193+
}
184194
/** Creates an array with given elements.
185195
*
186196
* @param xs the elements to put in the array

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,7 @@ private[collection] final class CNode[K, V](val bitmap: Int, val array: Array[Ba
487487
}
488488

489489
def updatedAt(pos: Int, nn: BasicNode, gen: Gen) = {
490-
val len = array.length
491-
val narr = new Array[BasicNode](len)
492-
Array.copy(array, 0, narr, 0, len)
490+
val narr = java.util.Arrays.copyOf(array, array.length)
493491
narr(pos) = nn
494492
new CNode[K, V](bitmap, narr, gen)
495493
}

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

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,9 @@ object ArrayBuilder {
133133
private var size: Int = 0
134134

135135
private def mkArray(size: Int): Array[Byte] = {
136-
val newelems = new Array[Byte](size)
137-
if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
138-
newelems
136+
if (size == 0) Array.emptyByteArray
137+
else if (elems eq null) new Array(size)
138+
else java.util.Arrays.copyOf(elems, size)
139139
}
140140

141141
private def resize(size: Int) {
@@ -198,9 +198,9 @@ object ArrayBuilder {
198198
private var size: Int = 0
199199

200200
private def mkArray(size: Int): Array[Short] = {
201-
val newelems = new Array[Short](size)
202-
if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
203-
newelems
201+
if (size == 0) Array.emptyShortArray
202+
else if (elems eq null) new Array(size)
203+
else java.util.Arrays.copyOf(elems, size)
204204
}
205205

206206
private def resize(size: Int) {
@@ -263,9 +263,9 @@ object ArrayBuilder {
263263
private var size: Int = 0
264264

265265
private def mkArray(size: Int): Array[Char] = {
266-
val newelems = new Array[Char](size)
267-
if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
268-
newelems
266+
if (size == 0) Array.emptyCharArray
267+
else if (elems eq null) new Array(size)
268+
else java.util.Arrays.copyOf(elems, size)
269269
}
270270

271271
private def resize(size: Int) {
@@ -328,9 +328,9 @@ object ArrayBuilder {
328328
private var size: Int = 0
329329

330330
private def mkArray(size: Int): Array[Int] = {
331-
val newelems = new Array[Int](size)
332-
if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
333-
newelems
331+
if (size == 0) Array.emptyIntArray
332+
else if (elems eq null) new Array(size)
333+
else java.util.Arrays.copyOf(elems, size)
334334
}
335335

336336
private def resize(size: Int) {
@@ -393,9 +393,9 @@ object ArrayBuilder {
393393
private var size: Int = 0
394394

395395
private def mkArray(size: Int): Array[Long] = {
396-
val newelems = new Array[Long](size)
397-
if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
398-
newelems
396+
if (size == 0) Array.emptyLongArray
397+
else if (elems eq null) new Array(size)
398+
else java.util.Arrays.copyOf(elems, size)
399399
}
400400

401401
private def resize(size: Int) {
@@ -458,9 +458,9 @@ object ArrayBuilder {
458458
private var size: Int = 0
459459

460460
private def mkArray(size: Int): Array[Float] = {
461-
val newelems = new Array[Float](size)
462-
if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
463-
newelems
461+
if (size == 0) Array.emptyFloatArray
462+
else if (elems eq null) new Array(size)
463+
else java.util.Arrays.copyOf(elems, size)
464464
}
465465

466466
private def resize(size: Int) {
@@ -523,9 +523,9 @@ object ArrayBuilder {
523523
private var size: Int = 0
524524

525525
private def mkArray(size: Int): Array[Double] = {
526-
val newelems = new Array[Double](size)
527-
if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
528-
newelems
526+
if (size == 0) Array.emptyDoubleArray
527+
else if (elems eq null) new Array(size)
528+
else java.util.Arrays.copyOf(elems, size)
529529
}
530530

531531
private def resize(size: Int) {
@@ -588,9 +588,9 @@ object ArrayBuilder {
588588
private var size: Int = 0
589589

590590
private def mkArray(size: Int): Array[Boolean] = {
591-
val newelems = new Array[Boolean](size)
592-
if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
593-
newelems
591+
if (size == 0) Array.emptyBooleanArray
592+
else if (elems eq null) new Array(size)
593+
else java.util.Arrays.copyOf(elems, size)
594594
}
595595

596596
private def resize(size: Int) {
@@ -663,10 +663,12 @@ object ArrayBuilder {
663663
def clear() { size = 0 }
664664

665665
def result() = {
666-
val ans = new Array[Unit](size)
667-
var i = 0
668-
while (i < size) { ans(i) = (); i += 1 }
669-
ans
666+
if (size == 0) Array.emptyUnitArray
667+
else {
668+
val ans = new Array[Unit](size)
669+
java.util.Arrays.fill(ans.asInstanceOf[Array[AnyRef]], ())
670+
ans
671+
}
670672
}
671673

672674
override def equals(other: Any): Boolean = other match {

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

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ class BitSet(protected final var elems: Array[Long]) extends AbstractSet[Int]
7373
if (idx >= nwords) {
7474
var newlen = nwords
7575
while (idx >= newlen) newlen = (newlen * 2) min MaxSize
76-
val elems1 = new Array[Long](newlen)
77-
Array.copy(elems, 0, elems1, 0, nwords)
78-
elems = elems1
76+
elems = java.util.Arrays.copyOf(elems, newlen)
7977
}
8078
}
8179

@@ -175,11 +173,8 @@ class BitSet(protected final var elems: Array[Long]) extends AbstractSet[Int]
175173
"immutability of the result.", "2.12.0")
176174
def toImmutable = immutable.BitSet.fromBitMaskNoCopy(elems)
177175

178-
override def clone(): BitSet = {
179-
val elems1 = new Array[Long](elems.length)
180-
Array.copy(elems, 0, elems1, 0, elems.length)
181-
new BitSet(elems1)
182-
}
176+
override def clone(): BitSet =
177+
new BitSet(elems.clone)
183178
}
184179

185180
/** $factoryInfo
@@ -198,13 +193,8 @@ object BitSet extends BitSetFactory[BitSet] {
198193
/** A bitset containing all the bits in an array */
199194
def fromBitMask(elems: Array[Long]): BitSet = {
200195
val len = elems.length
201-
if (len == 0) {
202-
empty
203-
} else {
204-
val a = new Array[Long](len)
205-
Array.copy(elems, 0, a, 0, len)
206-
new BitSet(a)
207-
}
196+
if (len == 0) empty
197+
else new BitSet(elems.clone)
208198
}
209199

210200
/** A bitset containing all the bits in an array, wrapping the existing

library/src/scala/collection/mutable/WrappedArrayBuilder.scala

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,45 @@ class WrappedArrayBuilder[A](tag: ClassTag[A]) extends ReusableBuilder[A, Wrappe
3535
private var size: Int = 0
3636

3737
private def mkArray(size: Int): WrappedArray[A] = {
38-
val runtimeClass = tag.runtimeClass
39-
val newelems = if (runtimeClass.isPrimitive) {
40-
runtimeClass match {
41-
case java.lang.Integer.TYPE => new WrappedArray.ofInt(new Array[Int](size)).asInstanceOf[WrappedArray[A]]
42-
case java.lang.Double.TYPE => new WrappedArray.ofDouble(new Array[Double](size)).asInstanceOf[WrappedArray[A]]
43-
case java.lang.Long.TYPE => new WrappedArray.ofLong(new Array[Long](size)).asInstanceOf[WrappedArray[A]]
44-
case java.lang.Float.TYPE => new WrappedArray.ofFloat(new Array[Float](size)).asInstanceOf[WrappedArray[A]]
45-
case java.lang.Character.TYPE => new WrappedArray.ofChar(new Array[Char](size)).asInstanceOf[WrappedArray[A]]
46-
case java.lang.Byte.TYPE => new WrappedArray.ofByte(new Array[Byte](size)).asInstanceOf[WrappedArray[A]]
47-
case java.lang.Short.TYPE => new WrappedArray.ofShort(new Array[Short](size)).asInstanceOf[WrappedArray[A]]
48-
case java.lang.Boolean.TYPE => new WrappedArray.ofBoolean(new Array[Boolean](size)).asInstanceOf[WrappedArray[A]]
49-
case java.lang.Void.TYPE => new WrappedArray.ofUnit(new Array[Unit](size)).asInstanceOf[WrappedArray[A]]
38+
if (size == 0) WrappedArrayBuilder.emptyWrappedArray(tag)
39+
else {
40+
import java.util.Arrays.copyOf
41+
val runtimeClass = tag.runtimeClass
42+
if (runtimeClass.isPrimitive)
43+
runtimeClass match {
44+
case java.lang.Integer.TYPE =>
45+
val array = if (elems eq null) new Array[Int](size) else copyOf(elems.array.asInstanceOf[Array[Int]], size)
46+
new WrappedArray.ofInt(array).asInstanceOf[WrappedArray[A]]
47+
case java.lang.Double.TYPE =>
48+
val array = if (elems eq null) new Array[Double](size) else copyOf(elems.array.asInstanceOf[Array[Double]], size)
49+
new WrappedArray.ofDouble(array).asInstanceOf[WrappedArray[A]]
50+
case java.lang.Long.TYPE =>
51+
val array = if (elems eq null) new Array[Long](size) else copyOf(elems.array.asInstanceOf[Array[Long]], size)
52+
new WrappedArray.ofLong(array).asInstanceOf[WrappedArray[A]]
53+
case java.lang.Float.TYPE =>
54+
val array = if (elems eq null) new Array[Float](size) else copyOf(elems.array.asInstanceOf[Array[Float]], size)
55+
new WrappedArray.ofFloat(array).asInstanceOf[WrappedArray[A]]
56+
case java.lang.Character.TYPE =>
57+
val array = if (elems eq null) new Array[Char](size) else copyOf(elems.array.asInstanceOf[Array[Char]], size)
58+
new WrappedArray.ofChar(array).asInstanceOf[WrappedArray[A]]
59+
case java.lang.Byte.TYPE =>
60+
val array = if (elems eq null) new Array[Byte](size) else copyOf(elems.array.asInstanceOf[Array[Byte]], size)
61+
new WrappedArray.ofByte(array).asInstanceOf[WrappedArray[A]]
62+
case java.lang.Short.TYPE =>
63+
val array = if (elems eq null) new Array[Short](size) else copyOf(elems.array.asInstanceOf[Array[Short]], size)
64+
new WrappedArray.ofShort(array).asInstanceOf[WrappedArray[A]]
65+
case java.lang.Boolean.TYPE =>
66+
val array = if (elems eq null) new Array[Boolean](size) else copyOf(elems.array.asInstanceOf[Array[Boolean]], size)
67+
new WrappedArray.ofBoolean(array).asInstanceOf[WrappedArray[A]]
68+
case java.lang.Void.TYPE =>
69+
val array = if (elems eq null) new Array[Unit](size) else copyOf(elems.array.asInstanceOf[Array[AnyRef]], size).asInstanceOf[Array[Unit]]
70+
new WrappedArray.ofUnit(array).asInstanceOf[WrappedArray[A]]
71+
}
72+
else {
73+
val array = if (elems eq null) new Array[A with AnyRef](size) else copyOf(elems.array.asInstanceOf[Array[A with AnyRef]], size)
74+
new WrappedArray.ofRef(array).asInstanceOf[WrappedArray[A]]
5075
}
51-
} else {
52-
new WrappedArray.ofRef[A with AnyRef](tag.newArray(size).asInstanceOf[Array[A with AnyRef]]).asInstanceOf[WrappedArray[A]]
5376
}
54-
if (this.size > 0) Array.copy(elems.array, 0, newelems.array, 0, this.size)
55-
newelems
5677
}
5778

5879
private def resize(size: Int) {
@@ -91,3 +112,24 @@ class WrappedArrayBuilder[A](tag: ClassTag[A]) extends ReusableBuilder[A, Wrappe
91112

92113
// todo: add ++=
93114
}
115+
private [mutable] object WrappedArrayBuilder {
116+
private def emptyWrappedArray[T](tag: ClassTag[T]): mutable.WrappedArray[T] =
117+
emptyClass.get(tag.runtimeClass).asInstanceOf[WrappedArray[T]]
118+
private[this] val emptyClass = new ClassValue[WrappedArray[_]] {
119+
override def computeValue(cls: Class[_]): WrappedArray[_] = {
120+
if (cls.isPrimitive)
121+
cls match {
122+
case java.lang.Integer.TYPE => new WrappedArray.ofInt(Array.emptyIntArray)
123+
case java.lang.Double.TYPE => new WrappedArray.ofDouble(Array.emptyDoubleArray)
124+
case java.lang.Long.TYPE => new WrappedArray.ofLong(Array.emptyLongArray)
125+
case java.lang.Float.TYPE => new WrappedArray.ofFloat(Array.emptyFloatArray)
126+
case java.lang.Character.TYPE => new WrappedArray.ofChar(Array.emptyCharArray)
127+
case java.lang.Byte.TYPE => new WrappedArray.ofByte(Array.emptyByteArray)
128+
case java.lang.Short.TYPE => new WrappedArray.ofShort(Array.emptyShortArray)
129+
case java.lang.Boolean.TYPE => new WrappedArray.ofBoolean(Array.emptyBooleanArray)
130+
case java.lang.Void.TYPE => new WrappedArray.ofUnit(Array.emptyUnitArray)
131+
}
132+
else new WrappedArray.ofRef(Array.empty.asInstanceOf[Array[_ <: AnyRef]])
133+
}
134+
}
135+
}

library/src/scala/collection/parallel/mutable/package.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,8 @@ package mutable {
6565
def internalArray = array
6666
def setInternalSize(s: Int) = size0 = s
6767
override def sizeHint(len: Int) = {
68-
if (len > size && len >= 1) {
69-
val newarray = new Array[AnyRef](len)
70-
Array.copy(array, 0, newarray, 0, size0)
71-
array = newarray
72-
}
68+
if (len > size && len >= 1)
69+
java.util.Arrays.copyOf(array, len)
7370
}
7471
}
7572

0 commit comments

Comments
 (0)