Do not use out projection for Array where appropriate.

This commit is contained in:
Ilya Gorbunov
2016-01-11 21:28:40 +03:00
parent eb5b5331fb
commit b99e1111f6
5 changed files with 37 additions and 31 deletions
+11 -12
View File
@@ -3618,8 +3618,8 @@ public fun ShortArray.slice(indices: Iterable<Int>): List<Short> {
/** /**
* Returns an array containing elements of this array at specified [indices]. * Returns an array containing elements of this array at specified [indices].
*/ */
public fun <T> Array<out T>.sliceArray(indices: Collection<Int>): Array<out T> { public fun <T> Array<T>.sliceArray(indices: Collection<Int>): Array<T> {
val result = arrayOfNulls(this, indices.size) as Array<T> val result = arrayOfNulls(this, indices.size)
var targetIndex = 0 var targetIndex = 0
for (sourceIndex in indices) { for (sourceIndex in indices) {
result[targetIndex++] = this[sourceIndex] result[targetIndex++] = this[sourceIndex]
@@ -3726,7 +3726,7 @@ public fun ShortArray.sliceArray(indices: Collection<Int>): ShortArray {
/** /**
* Returns a list containing elements at indices in the specified [indices] range. * Returns a list containing elements at indices in the specified [indices] range.
*/ */
public fun <T> Array<out T>.sliceArray(indices: IntRange): Array<out T> { public fun <T> Array<T>.sliceArray(indices: IntRange): Array<T> {
if (indices.isEmpty()) return copyOfRange(0, 0) if (indices.isEmpty()) return copyOfRange(0, 0)
return copyOfRange(indices.start, indices.endInclusive + 1) return copyOfRange(indices.start, indices.endInclusive + 1)
} }
@@ -4302,15 +4302,14 @@ public inline fun ShortArray.takeWhile(predicate: (Short) -> Boolean): List<Shor
/** /**
* Reverses elements in the array in-place. * Reverses elements in the array in-place.
*/ */
public fun <T> Array<out T>.reverse(): Unit { public fun <T> Array<T>.reverse(): Unit {
val midPoint = (size / 2) - 1 val midPoint = (size / 2) - 1
if (midPoint < 0) return if (midPoint < 0) return
val _this = this as Array<T>
var reverseIndex = lastIndex var reverseIndex = lastIndex
for (index in 0..midPoint) { for (index in 0..midPoint) {
val tmp = _this[index] val tmp = this[index]
_this[index] = _this[reverseIndex] this[index] = this[reverseIndex]
_this[reverseIndex] = tmp this[reverseIndex] = tmp
reverseIndex-- reverseIndex--
} }
} }
@@ -4528,9 +4527,9 @@ public fun ShortArray.reversed(): List<Short> {
/** /**
* Returns an array with elements of this array in reversed order. * Returns an array with elements of this array in reversed order.
*/ */
public fun <T> Array<out T>.reversedArray(): Array<out T> { public fun <T> Array<T>.reversedArray(): Array<T> {
if (isEmpty()) return this if (isEmpty()) return this
val result = arrayOfNulls(this, size) as Array<T> val result = arrayOfNulls(this, size)
val lastIndex = lastIndex val lastIndex = lastIndex
for (i in 0..lastIndex) for (i in 0..lastIndex)
result[lastIndex - i] = this[i] result[lastIndex - i] = this[i]
@@ -4783,7 +4782,7 @@ public fun ShortArray.sorted(): List<Short> {
/** /**
* Returns an array with all elements of this array sorted according to their natural sort order. * Returns an array with all elements of this array sorted according to their natural sort order.
*/ */
public fun <T : Comparable<T>> Array<out T>.sortedArray(): Array<out T> { public fun <T : Comparable<T>> Array<T>.sortedArray(): Array<T> {
if (isEmpty()) return this if (isEmpty()) return this
return this.copyOf().apply { sort() } return this.copyOf().apply { sort() }
} }
@@ -4847,7 +4846,7 @@ public fun ShortArray.sortedArray(): ShortArray {
/** /**
* Returns an array with all elements of this array sorted descending according to their natural sort order. * Returns an array with all elements of this array sorted descending according to their natural sort order.
*/ */
public fun <T : Comparable<T>> Array<out T>.sortedArrayDescending(): Array<out T> { public fun <T : Comparable<T>> Array<T>.sortedArrayDescending(): Array<T> {
if (isEmpty()) return this if (isEmpty()) return this
return this.copyOf().apply { sortWith(reverseOrder()) } return this.copyOf().apply { sortWith(reverseOrder()) }
} }
@@ -87,6 +87,6 @@ public inline fun <reified T> Collection<T>.toTypedArray(): Array<T> {
public inline fun <reified T> Array<out T>?.orEmpty(): Array<out T> = this ?: arrayOf<T>() public inline fun <reified T> Array<out T>?.orEmpty(): Array<out T> = this ?: arrayOf<T>()
/** Internal unsafe construction of array based on reference array type */ /** Internal unsafe construction of array based on reference array type */
internal fun <T> arrayOfNulls(reference: Array<out T>, size: Int): Array<out T> { internal fun <T> arrayOfNulls(reference: Array<T>, size: Int): Array<T> {
return java.lang.reflect.Array.newInstance(reference.javaClass.componentType, size) as Array<out T> return java.lang.reflect.Array.newInstance(reference.javaClass.componentType, size) as Array<T>
} }
@@ -495,8 +495,10 @@ class ArraysTest {
val coll: Collection<Int> = listOf(3, 1, 2) val coll: Collection<Int> = listOf(3, 1, 2)
assertArrayNotSameButEquals(arrayOf("B"), arrayOf("A", "B", "C").sliceArray(1..1)) assertArrayNotSameButEquals(arrayOf("B"), arrayOf("A", "B", "C").sliceArray(1..1))
assertArrayNotSameButEquals(arrayOf("B"), (arrayOf("A", "B", "C") as Array<out String>).sliceArray(1..1))
assertArrayNotSameButEquals(arrayOf('E', 'B', 'C'), arrayOf('A', 'B', 'C', 'E').sliceArray(coll)) assertArrayNotSameButEquals(arrayOf('E', 'B', 'C'), arrayOf('A', 'B', 'C', 'E').sliceArray(coll))
assertArrayNotSameButEquals(arrayOf<Int>(), arrayOf<Int>().sliceArray(5..4)) assertArrayNotSameButEquals(arrayOf<Int>(), arrayOf<Int>().sliceArray(5..4))
assertArrayNotSameButEquals(intArrayOf(), intArrayOf(1, 2, 3).sliceArray(5..1)) assertArrayNotSameButEquals(intArrayOf(), intArrayOf(1, 2, 3).sliceArray(5..1))
assertArrayNotSameButEquals(intArrayOf(2, 3, 9), intArrayOf(2, 3, 9, 2, 3, 9).sliceArray(coll)) assertArrayNotSameButEquals(intArrayOf(2, 3, 9), intArrayOf(2, 3, 9, 2, 3, 9).sliceArray(coll))
@@ -655,6 +657,7 @@ class ArraysTest {
doTest(build = { map {'a' + it}.toCharArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {'a' + it}.toCharArray() }, reverse = { reverse() }, snapshot = { toList() })
doTest(build = { map {it % 2 == 0}.toBooleanArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it % 2 == 0}.toBooleanArray() }, reverse = { reverse() }, snapshot = { toList() })
doTest(build = { map {it.toString()}.toTypedArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toString()}.toTypedArray() }, reverse = { reverse() }, snapshot = { toList() })
doTest(build = { map {it.toString()}.toTypedArray() as Array<out String> }, reverse = { reverse() }, snapshot = { toList() })
} }
@@ -680,6 +683,7 @@ class ArraysTest {
assertArrayNotSameButEquals(charArrayOf('3', '2', '1'), charArrayOf('1', '2', '3').reversedArray()) assertArrayNotSameButEquals(charArrayOf('3', '2', '1'), charArrayOf('1', '2', '3').reversedArray())
assertArrayNotSameButEquals(booleanArrayOf(false, false, true), booleanArrayOf(true, false, false).reversedArray()) assertArrayNotSameButEquals(booleanArrayOf(false, false, true), booleanArrayOf(true, false, false).reversedArray())
assertArrayNotSameButEquals(arrayOf("3", "2", "1"), arrayOf("1", "2", "3").reversedArray()) assertArrayNotSameButEquals(arrayOf("3", "2", "1"), arrayOf("1", "2", "3").reversedArray())
assertArrayNotSameButEquals(arrayOf("3", "2", "1"), (arrayOf("1", "2", "3") as Array<out String>).reversedArray())
} }
@test fun drop() { @test fun drop() {
@@ -971,6 +975,11 @@ class ArraysTest {
fun <A, T: Comparable<T>> arrayData(vararg values: T, toArray: Array<out T>.() -> A) = ArraySortedChecker<A, T>(values.toArray(), naturalOrder()) fun <A, T: Comparable<T>> arrayData(vararg values: T, toArray: Array<out T>.() -> A) = ArraySortedChecker<A, T>(values.toArray(), naturalOrder())
with (arrayData("ac", "aD", "aba") { toList().toTypedArray() }) { with (arrayData("ac", "aD", "aba") { toList().toTypedArray() }) {
checkSorted<List<String>>({ sorted() }, { sortedDescending() }, { iterator() })
checkSorted<Array<String>>({ sortedArray() }, { sortedArrayDescending()}, { iterator() } )
}
with (arrayData("ac", "aD", "aba") { toList().toTypedArray() as Array<out String> }) {
checkSorted<List<String>>({ sorted() }, { sortedDescending() }, { iterator() }) checkSorted<List<String>>({ sorted() }, { sortedDescending() }, { iterator() })
checkSorted<Array<out String>>({ sortedArray() }, { sortedArrayDescending()}, { iterator() } ) checkSorted<Array<out String>>({ sortedArray() }, { sortedArrayDescending()}, { iterator() } )
} }
@@ -585,12 +585,12 @@ fun filtering(): List<GenericFunction> {
} }
templates add f("sliceArray(indices: Collection<Int>)") { templates add f("sliceArray(indices: Collection<Int>)") {
only(ArraysOfObjects, ArraysOfPrimitives) only(InvariantArraysOfObjects, ArraysOfPrimitives)
doc { "Returns an array containing elements of this array at specified [indices]." } doc { "Returns an array containing elements of this array at specified [indices]." }
returns("SELF") returns("SELF")
body(ArraysOfObjects) { body(InvariantArraysOfObjects) {
""" """
val result = arrayOfNulls(this, indices.size) as Array<T> val result = arrayOfNulls(this, indices.size)
var targetIndex = 0 var targetIndex = 0
for (sourceIndex in indices) { for (sourceIndex in indices) {
result[targetIndex++] = this[sourceIndex] result[targetIndex++] = this[sourceIndex]
@@ -611,10 +611,10 @@ fun filtering(): List<GenericFunction> {
} }
templates add f("sliceArray(indices: IntRange)") { templates add f("sliceArray(indices: IntRange)") {
only(ArraysOfObjects, ArraysOfPrimitives) only(InvariantArraysOfObjects, ArraysOfPrimitives)
doc { "Returns a list containing elements at indices in the specified [indices] range." } doc { "Returns a list containing elements at indices in the specified [indices] range." }
returns("SELF") returns("SELF")
body(ArraysOfObjects) { body(InvariantArraysOfObjects) {
""" """
if (indices.isEmpty()) return copyOfRange(0, 0) if (indices.isEmpty()) return copyOfRange(0, 0)
return copyOfRange(indices.start, indices.endInclusive + 1) return copyOfRange(indices.start, indices.endInclusive + 1)
@@ -7,20 +7,18 @@ fun ordering(): List<GenericFunction> {
templates add f("reverse()") { templates add f("reverse()") {
doc { f -> "Reverses ${f.element.pluralize()} in the ${f.collection} in-place." } doc { f -> "Reverses ${f.element.pluralize()} in the ${f.collection} in-place." }
only(Lists, ArraysOfObjects, ArraysOfPrimitives) only(Lists, InvariantArraysOfObjects, ArraysOfPrimitives)
customReceiver(Lists) { "MutableList<T>" } customReceiver(Lists) { "MutableList<T>" }
returns { "Unit" } returns { "Unit" }
body { f -> body { f ->
val _this = if (f == ArraysOfObjects) "_this" else "this"
""" """
val midPoint = (size / 2) - 1 val midPoint = (size / 2) - 1
if (midPoint < 0) return if (midPoint < 0) return
${if (f == ArraysOfObjects) "val _this = this as Array<T>" else "" }
var reverseIndex = lastIndex var reverseIndex = lastIndex
for (index in 0..midPoint) { for (index in 0..midPoint) {
val tmp = $_this[index] val tmp = this[index]
$_this[index] = $_this[reverseIndex] this[index] = this[reverseIndex]
$_this[reverseIndex] = tmp this[reverseIndex] = tmp
reverseIndex-- reverseIndex--
} }
""" """
@@ -62,12 +60,12 @@ fun ordering(): List<GenericFunction> {
templates add f("reversedArray()") { templates add f("reversedArray()") {
doc { "Returns an array with elements of this array in reversed order." } doc { "Returns an array with elements of this array in reversed order." }
only(ArraysOfObjects, ArraysOfPrimitives) only(InvariantArraysOfObjects, ArraysOfPrimitives)
returns("SELF") returns("SELF")
body(ArraysOfObjects) { body(InvariantArraysOfObjects) {
""" """
if (isEmpty()) return this if (isEmpty()) return this
val result = arrayOfNulls(this, size) as Array<T> val result = arrayOfNulls(this, size)
val lastIndex = lastIndex val lastIndex = lastIndex
for (i in 0..lastIndex) for (i in 0..lastIndex)
result[lastIndex - i] = this[i] result[lastIndex - i] = this[i]
@@ -134,7 +132,7 @@ fun ordering(): List<GenericFunction> {
} }
templates add f("sortedArray()") { templates add f("sortedArray()") {
only(ArraysOfObjects, ArraysOfPrimitives) only(InvariantArraysOfObjects, ArraysOfPrimitives)
exclude(PrimitiveType.Boolean) exclude(PrimitiveType.Boolean)
doc { doc {
"Returns an array with all elements of this array sorted according to their natural sort order." "Returns an array with all elements of this array sorted according to their natural sort order."
@@ -196,14 +194,14 @@ fun ordering(): List<GenericFunction> {
} }
templates add f("sortedArrayDescending()") { templates add f("sortedArrayDescending()") {
only(ArraysOfObjects, ArraysOfPrimitives) only(InvariantArraysOfObjects, ArraysOfPrimitives)
exclude(PrimitiveType.Boolean) exclude(PrimitiveType.Boolean)
doc { doc {
"Returns an array with all elements of this array sorted descending according to their natural sort order." "Returns an array with all elements of this array sorted descending according to their natural sort order."
} }
typeParam("T : Comparable<T>") typeParam("T : Comparable<T>")
returns("SELF") returns("SELF")
body(ArraysOfObjects) { body(InvariantArraysOfObjects) {
""" """
if (isEmpty()) return this if (isEmpty()) return this
return this.copyOf().apply { sortWith(reverseOrder()) } return this.copyOf().apply { sortWith(reverseOrder()) }