KT-57617 Delegate iterators of reversed list views to underlying list iterators

Improve the performance of reversed list view iterators by delegating to
underlying list iterators instead of using implementations provided by
the AbstractList.
Latter use AbstractList::get(index: Int) to implement next() and
previous() methods and depending on the underlying list's implementation
it may lead to worse performance.

The change also improves reversed list views test coverage.
This commit is contained in:
Filipp Zhinkin
2023-04-06 16:12:28 +02:00
committed by Space Team
parent 247f5529d2
commit d0847f2519
2 changed files with 202 additions and 33 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -11,6 +11,19 @@ package kotlin.collections
private open class ReversedListReadOnly<out T>(private val delegate: List<T>) : AbstractList<T>() {
override val size: Int get() = delegate.size
override fun get(index: Int): T = delegate[reverseElementIndex(index)]
override fun iterator(): Iterator<T> = listIterator(0)
override fun listIterator(): ListIterator<T> = listIterator(0)
override fun listIterator(index: Int): ListIterator<T> = object : ListIterator<T> {
val delegateIterator = delegate.listIterator(reversePositionIndex(index))
override fun hasNext(): Boolean = delegateIterator.hasPrevious()
override fun hasPrevious(): Boolean = delegateIterator.hasNext()
override fun next(): T = delegateIterator.previous()
override fun nextIndex(): Int = reverseIteratorIndex(delegateIterator.previousIndex())
override fun previous(): T = delegateIterator.next()
override fun previousIndex(): Int = reverseIteratorIndex(delegateIterator.nextIndex())
}
}
private class ReversedList<T>(private val delegate: MutableList<T>) : AbstractMutableList<T>() {
@@ -24,6 +37,28 @@ private class ReversedList<T>(private val delegate: MutableList<T>) : AbstractMu
override fun add(index: Int, element: T) {
delegate.add(reversePositionIndex(index), element)
}
override fun iterator(): MutableIterator<T> = listIterator(0)
override fun listIterator(): MutableListIterator<T> = listIterator(0)
override fun listIterator(index: Int): MutableListIterator<T> = object : MutableListIterator<T> {
val delegateIterator = delegate.listIterator(reversePositionIndex(index))
override fun hasNext(): Boolean = delegateIterator.hasPrevious()
override fun hasPrevious(): Boolean = delegateIterator.hasNext()
override fun next(): T = delegateIterator.previous()
override fun nextIndex(): Int = reverseIteratorIndex(delegateIterator.previousIndex())
override fun previous(): T = delegateIterator.next()
override fun previousIndex(): Int = reverseIteratorIndex(delegateIterator.nextIndex())
override fun add(element: T) {
delegateIterator.add(element)
// After an insertion previous() will return an inserted element.
// Moving a cursor back by one element to return a correct value from next().
delegateIterator.previous()
}
override fun remove() = delegateIterator.remove()
override fun set(element: T) = delegateIterator.set(element)
}
}
private fun List<*>.reverseElementIndex(index: Int) =
@@ -32,6 +67,7 @@ private fun List<*>.reverseElementIndex(index: Int) =
private fun List<*>.reversePositionIndex(index: Int) =
if (index in 0..size) size - index else throw IndexOutOfBoundsException("Position index $index must be in range [${0..size}].")
private fun List<*>.reverseIteratorIndex(index: Int) = lastIndex - index
/**
* Returns a reversed read-only view of the original List.