Use list iterators instead of indexed access in operations on lists taking a lambda.

Related to #KT-9607
This commit is contained in:
Ilya Gorbunov
2016-02-11 23:54:49 +03:00
parent b743e71cfc
commit f4f82656f7
5 changed files with 217 additions and 45 deletions
@@ -401,6 +401,19 @@ fun aggregates(): List<GenericFunction> {
return accumulator
"""
}
body(Lists) {
"""
var accumulator = initial
if (!isEmpty()) {
val iterator = listIterator(size)
while (iterator.hasPrevious()) {
val index = iterator.previousIndex()
accumulator = operation(index, iterator.previous(), accumulator)
}
}
return accumulator
"""
}
}
templates add f("fold(initial: R, operation: (R, T) -> R)") {
@@ -436,6 +449,18 @@ fun aggregates(): List<GenericFunction> {
return accumulator
"""
}
body(Lists) {
"""
var accumulator = initial
if (!isEmpty()) {
val iterator = listIterator(size)
while (iterator.hasPrevious()) {
accumulator = operation(iterator.previous(), accumulator)
}
}
return accumulator
"""
}
}
templates add f("reduceIndexed(operation: (Int, T, T) -> T)") {
@@ -562,6 +587,21 @@ fun aggregates(): List<GenericFunction> {
--index
}
return accumulator
"""
}
body(Lists) {
"""
val iterator = listIterator(size)
if (!iterator.hasPrevious())
throw UnsupportedOperationException("Empty list can't be reduced.")
var accumulator: S = iterator.previous()
while (iterator.hasPrevious()) {
val index = iterator.previousIndex()
accumulator = operation(index, iterator.previous(), accumulator)
}
return accumulator
"""
}
@@ -660,6 +700,20 @@ fun aggregates(): List<GenericFunction> {
accumulator = operation(get(index--), accumulator)
}
return accumulator
"""
}
body(Lists) {
"""
val iterator = listIterator(size)
if (!iterator.hasPrevious())
throw UnsupportedOperationException("Empty list can't be reduced.")
var accumulator: S = iterator.previous()
while (iterator.hasPrevious()) {
accumulator = operation(iterator.previous(), accumulator)
}
return accumulator
"""
}
@@ -130,6 +130,7 @@ fun elements(): List<GenericFunction> {
templates add f("indexOfFirst(predicate: (T) -> Boolean)") {
inline(true)
include(Lists)
doc { f -> "Returns index of the first ${f.element} matching the given [predicate], or -1 if the ${f.collection} does not contain such ${f.element}." }
returns("Int")
body {
@@ -144,7 +145,7 @@ fun elements(): List<GenericFunction> {
"""
}
body(Lists, CharSequences, ArraysOfPrimitives, ArraysOfObjects) {
body(CharSequences, ArraysOfPrimitives, ArraysOfObjects) {
"""
for (index in indices) {
if (predicate(this[index])) {
@@ -174,7 +175,7 @@ fun elements(): List<GenericFunction> {
"""
}
body(Lists, CharSequences, ArraysOfPrimitives, ArraysOfObjects) {
body(CharSequences, ArraysOfPrimitives, ArraysOfObjects) {
"""
for (index in indices.reversed()) {
if (predicate(this[index])) {
@@ -184,6 +185,17 @@ fun elements(): List<GenericFunction> {
return -1
"""
}
body(Lists) {
"""
val iterator = this.listIterator(size)
while (iterator.hasPrevious()) {
if (predicate(iterator.previous())) {
return iterator.nextIndex()
}
}
return -1
"""
}
}
templates add f("elementAt(index: Int)") {
@@ -535,7 +547,7 @@ fun elements(): List<GenericFunction> {
"""
}
body(CharSequences, ArraysOfPrimitives, ArraysOfObjects, Lists) { f ->
body(CharSequences, ArraysOfPrimitives, ArraysOfObjects) { f ->
"""
for (index in this.indices.reversed()) {
val element = this[index]
@@ -544,6 +556,16 @@ fun elements(): List<GenericFunction> {
throw NoSuchElementException("${f.doc.collection.capitalize()} contains no ${f.doc.element} matching the predicate.")
"""
}
body(Lists) { f ->
"""
val iterator = this.listIterator(size)
while (iterator.hasPrevious()) {
val element = iterator.previous()
if (predicate(element)) return element
}
throw NoSuchElementException("${f.doc.collection.capitalize()} contains no ${f.doc.element} matching the predicate.")
"""
}
}
templates add f("lastOrNull(predicate: (T) -> Boolean)") {
@@ -569,7 +591,7 @@ fun elements(): List<GenericFunction> {
"""
}
body(CharSequences, ArraysOfPrimitives, ArraysOfObjects, Lists) {
body(CharSequences, ArraysOfPrimitives, ArraysOfObjects) {
"""
for (index in this.indices.reversed()) {
val element = this[index]
@@ -578,6 +600,17 @@ fun elements(): List<GenericFunction> {
return null
"""
}
body(Lists) {
"""
val iterator = this.listIterator(size)
while (iterator.hasPrevious()) {
val element = iterator.previous()
if (predicate(element)) return element
}
return null
"""
}
}
templates add f("findLast(predicate: (T) -> Boolean)") {
@@ -49,8 +49,8 @@ fun filtering(): List<GenericFunction> {
list = ArrayList<T>(resultSize)
if (this is List<T>) {
for (index in n..size - 1) {
list.add(this[index])
for (item in listIterator(n)) {
list.add(item)
}
return list
}
@@ -202,7 +202,7 @@ fun filtering(): List<GenericFunction> {
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
require(n >= 0) { "Requested element count $n is less than zero." }
if (n == 0) return emptyList()
@@ -214,6 +214,23 @@ fun filtering(): List<GenericFunction> {
return list
"""
}
body(Lists) {
"""
require(n >= 0) { "Requested element count $n is less than zero." }
if (n == 0) return emptyList()
val size = size
if (n >= size) return toList()
val list = ArrayList<T>(n)
if (this is RandomAccess) {
for (index in size - n .. size - 1)
list.add(this[index])
} else {
for (item in listIterator(n))
list.add(item)
}
return list
"""
}
}
templates add f("dropWhile(predicate: (T) -> Boolean)") {
@@ -316,6 +333,19 @@ fun filtering(): List<GenericFunction> {
return emptyList()
"""
}
body(Lists) {
"""
if (!isEmpty()) {
val iterator = listIterator(size)
while (iterator.hasPrevious()) {
if (!predicate(iterator.previous())) {
return take(iterator.nextIndex() + 1)
}
}
}
return emptyList()
"""
}
doc(Strings) { "Returns a string containing all characters except last characters that satisfy the given [predicate]." }
doc(CharSequences) { "Returns a subsequence of this char sequence containing all characters except last characters that satisfy the given [predicate]." }
@@ -347,6 +377,27 @@ fun filtering(): List<GenericFunction> {
return toList()
"""
}
body(Lists) {
"""
if (isEmpty())
return emptyList()
val iterator = listIterator(size)
while (iterator.hasPrevious()) {
if (!predicate(iterator.previous())) {
iterator.next()
val expectedSize = size - iterator.nextIndex()
if (expectedSize == 0) return emptyList()
return ArrayList<T>(expectedSize).apply {
while (iterator.hasNext())
add(iterator.next())
}
}
}
return toList()
"""
// TODO: Use iterator.toList() internal method in 1.1
// return iterator.toList(size - iterator.nextIndex())
}
doc(Strings) { "Returns a string containing last characters that satisfy the given [predicate]." }
doc(CharSequences) { "Returns a subsequence of this char sequence containing last characters that satisfy the given [predicate]." }