Skip to content

Commit

Permalink
Merge pull request #8946 from japgolly/topic/avoidBoxingInArraySeq
Browse files Browse the repository at this point in the history
  • Loading branch information
lrytz committed May 6, 2020
2 parents a2d7283 + a34b259 commit 5e559ef
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 0 deletions.
120 changes: 120 additions & 0 deletions src/library/scala/collection/immutable/ArraySeq.scala
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,21 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self =>
AnyStepper.ofParIntStepper(new WidenedByteArrayStepper(unsafeArray, 0, unsafeArray.length))
else new WidenedByteArrayStepper(unsafeArray, 0, unsafeArray.length)
).asInstanceOf[S with EfficientSplit]
override def updated[B >: Byte](index: Int, elem: B): ArraySeq[B] =
elem match {
case b: Byte => new ArraySeq.ofByte(unsafeArray.updated(index, b))
case _ => super.updated(index, elem)
}
override def appended[B >: Byte](elem: B): ArraySeq[B] =
elem match {
case b: Byte => new ArraySeq.ofByte(unsafeArray.appended(b))
case _ => super.appended(elem)
}
override def prepended[B >: Byte](elem: B): ArraySeq[B] =
elem match {
case b: Byte => new ArraySeq.ofByte(unsafeArray.prepended(b))
case _ => super.prepended(elem)
}
}

@SerialVersionUID(3L)
Expand All @@ -397,6 +412,21 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self =>
AnyStepper.ofParIntStepper(new WidenedShortArrayStepper(unsafeArray, 0, unsafeArray.length))
else new WidenedShortArrayStepper(unsafeArray, 0, unsafeArray.length)
).asInstanceOf[S with EfficientSplit]
override def updated[B >: Short](index: Int, elem: B): ArraySeq[B] =
elem match {
case b: Short => new ArraySeq.ofShort(unsafeArray.updated(index, b))
case _ => super.updated(index, elem)
}
override def appended[B >: Short](elem: B): ArraySeq[B] =
elem match {
case b: Short => new ArraySeq.ofShort(unsafeArray.appended(b))
case _ => super.appended(elem)
}
override def prepended[B >: Short](elem: B): ArraySeq[B] =
elem match {
case b: Short => new ArraySeq.ofShort(unsafeArray.prepended(b))
case _ => super.prepended(elem)
}
}

@SerialVersionUID(3L)
Expand All @@ -423,6 +453,21 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self =>
AnyStepper.ofParIntStepper(new WidenedCharArrayStepper(unsafeArray, 0, unsafeArray.length))
else new WidenedCharArrayStepper(unsafeArray, 0, unsafeArray.length)
).asInstanceOf[S with EfficientSplit]
override def updated[B >: Char](index: Int, elem: B): ArraySeq[B] =
elem match {
case b: Char => new ArraySeq.ofChar(unsafeArray.updated(index, b))
case _ => super.updated(index, elem)
}
override def appended[B >: Char](elem: B): ArraySeq[B] =
elem match {
case b: Char => new ArraySeq.ofChar(unsafeArray.appended(b))
case _ => super.appended(elem)
}
override def prepended[B >: Char](elem: B): ArraySeq[B] =
elem match {
case b: Char => new ArraySeq.ofChar(unsafeArray.prepended(b))
case _ => super.prepended(elem)
}

override def addString(sb: StringBuilder, start: String, sep: String, end: String): StringBuilder =
(new MutableArraySeq.ofChar(unsafeArray)).addString(sb, start, sep, end)
Expand Down Expand Up @@ -452,6 +497,21 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self =>
AnyStepper.ofParIntStepper(new IntArrayStepper(unsafeArray, 0, unsafeArray.length))
else new IntArrayStepper(unsafeArray, 0, unsafeArray.length)
).asInstanceOf[S with EfficientSplit]
override def updated[B >: Int](index: Int, elem: B): ArraySeq[B] =
elem match {
case b: Int => new ArraySeq.ofInt(unsafeArray.updated(index, b))
case _ => super.updated(index, elem)
}
override def appended[B >: Int](elem: B): ArraySeq[B] =
elem match {
case b: Int => new ArraySeq.ofInt(unsafeArray.appended(b))
case _ => super.appended(elem)
}
override def prepended[B >: Int](elem: B): ArraySeq[B] =
elem match {
case b: Int => new ArraySeq.ofInt(unsafeArray.prepended(b))
case _ => super.prepended(elem)
}
}

@SerialVersionUID(3L)
Expand All @@ -478,6 +538,21 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self =>
AnyStepper.ofParLongStepper(new LongArrayStepper(unsafeArray, 0, unsafeArray.length))
else new LongArrayStepper(unsafeArray, 0, unsafeArray.length)
).asInstanceOf[S with EfficientSplit]
override def updated[B >: Long](index: Int, elem: B): ArraySeq[B] =
elem match {
case b: Long => new ArraySeq.ofLong(unsafeArray.updated(index, b))
case _ => super.updated(index, elem)
}
override def appended[B >: Long](elem: B): ArraySeq[B] =
elem match {
case b: Long => new ArraySeq.ofLong(unsafeArray.appended(b))
case _ => super.appended(elem)
}
override def prepended[B >: Long](elem: B): ArraySeq[B] =
elem match {
case b: Long => new ArraySeq.ofLong(unsafeArray.prepended(b))
case _ => super.prepended(elem)
}
}

@SerialVersionUID(3L)
Expand All @@ -497,6 +572,21 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self =>
AnyStepper.ofParDoubleStepper(new WidenedFloatArrayStepper(unsafeArray, 0, unsafeArray.length))
else new WidenedFloatArrayStepper(unsafeArray, 0, unsafeArray.length)
).asInstanceOf[S with EfficientSplit]
override def updated[B >: Float](index: Int, elem: B): ArraySeq[B] =
elem match {
case b: Float => new ArraySeq.ofFloat(unsafeArray.updated(index, b))
case _ => super.updated(index, elem)
}
override def appended[B >: Float](elem: B): ArraySeq[B] =
elem match {
case b: Float => new ArraySeq.ofFloat(unsafeArray.appended(b))
case _ => super.appended(elem)
}
override def prepended[B >: Float](elem: B): ArraySeq[B] =
elem match {
case b: Float => new ArraySeq.ofFloat(unsafeArray.prepended(b))
case _ => super.prepended(elem)
}
}

@SerialVersionUID(3L)
Expand All @@ -516,6 +606,21 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self =>
AnyStepper.ofParDoubleStepper(new DoubleArrayStepper(unsafeArray, 0, unsafeArray.length))
else new DoubleArrayStepper(unsafeArray, 0, unsafeArray.length)
).asInstanceOf[S with EfficientSplit]
override def updated[B >: Double](index: Int, elem: B): ArraySeq[B] =
elem match {
case b: Double => new ArraySeq.ofDouble(unsafeArray.updated(index, b))
case _ => super.updated(index, elem)
}
override def appended[B >: Double](elem: B): ArraySeq[B] =
elem match {
case b: Double => new ArraySeq.ofDouble(unsafeArray.appended(b))
case _ => super.appended(elem)
}
override def prepended[B >: Double](elem: B): ArraySeq[B] =
elem match {
case b: Double => new ArraySeq.ofDouble(unsafeArray.prepended(b))
case _ => super.prepended(elem)
}
}

@SerialVersionUID(3L)
Expand All @@ -539,6 +644,21 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self =>
override def iterator: Iterator[Boolean] = new ArrayOps.ArrayIterator[Boolean](unsafeArray)
override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Boolean, S]): S with EfficientSplit =
new BoxedBooleanArrayStepper(unsafeArray, 0, unsafeArray.length).asInstanceOf[S with EfficientSplit]
override def updated[B >: Boolean](index: Int, elem: B): ArraySeq[B] =
elem match {
case b: Boolean => new ArraySeq.ofBoolean(unsafeArray.updated(index, b))
case _ => super.updated(index, elem)
}
override def appended[B >: Boolean](elem: B): ArraySeq[B] =
elem match {
case b: Boolean => new ArraySeq.ofBoolean(unsafeArray.appended(b))
case _ => super.appended(elem)
}
override def prepended[B >: Boolean](elem: B): ArraySeq[B] =
elem match {
case b: Boolean => new ArraySeq.ofBoolean(unsafeArray.prepended(b))
case _ => super.prepended(elem)
}
}

@SerialVersionUID(3L)
Expand Down
35 changes: 35 additions & 0 deletions test/junit/scala/collection/immutable/ArraySeqTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,41 @@ class ArraySeqTest {
assertEquals(x.hashCode(), y.hashCode())
}

private def assertArraySeqAndType[A](actual: ArraySeq[A], expect: ArraySeq[A], expectedArrayType: Class[_]): Unit = {
assertEquals(actual, expect)
assertEquals(actual.unsafeArray.getClass(), expectedArrayType)
}

@Test
def appendInt(): Unit = {
assertArraySeqAndType(ArraySeq(1, 3) :+ 7, ArraySeq(1, 3, 7), classOf[Array[Int]])
}

@Test
def appendAny(): Unit = {
assertArraySeqAndType(ArraySeq(1, 3) :+ "x", ArraySeq[Any](1, 3, "x"), classOf[Array[AnyRef]])
}

@Test
def prependInt(): Unit = {
assertArraySeqAndType(87 +: ArraySeq(1, 3), ArraySeq(87, 1, 3), classOf[Array[Int]])
}

@Test
def prependAny(): Unit = {
assertArraySeqAndType("x" +: ArraySeq(1, 3), ArraySeq[Any]("x", 1, 3), classOf[Array[AnyRef]])
}

@Test
def updatedInt(): Unit = {
assertArraySeqAndType(ArraySeq(1, 2).updated(0, 3), ArraySeq(3, 2), classOf[Array[Int]])
}

@Test
def updatedAny(): Unit = {
assertArraySeqAndType(ArraySeq(1, 2).updated(0, "x"), ArraySeq[Any]("x", 2), classOf[Array[AnyRef]])
}

@Test
def foldInt(): Unit = {
val a = ArraySeq(1, 3)
Expand Down

0 comments on commit 5e559ef

Please sign in to comment.