KT-58588 Optimize Sequence::flatten
Rewrite FlatteningSequence to use the same optimization technique as AbstractIterator. Didn't extend AbstractIterator as storing and reloading a value from a field is slightly slower compared to the implemented approach.
This commit is contained in:
committed by
Space Team
parent
7ca506870a
commit
e803977924
@@ -289,37 +289,55 @@ constructor(
|
|||||||
private val transformer: (T) -> R,
|
private val transformer: (T) -> R,
|
||||||
private val iterator: (R) -> Iterator<E>
|
private val iterator: (R) -> Iterator<E>
|
||||||
) : Sequence<E> {
|
) : Sequence<E> {
|
||||||
|
private object State {
|
||||||
|
const val UNDEFINED = 0
|
||||||
|
const val READY = 1
|
||||||
|
const val DONE = 2
|
||||||
|
}
|
||||||
|
|
||||||
override fun iterator(): Iterator<E> = object : Iterator<E> {
|
override fun iterator(): Iterator<E> = object : Iterator<E> {
|
||||||
val iterator = sequence.iterator()
|
val iterator = sequence.iterator()
|
||||||
var itemIterator: Iterator<E>? = null
|
var itemIterator: Iterator<E>? = null
|
||||||
|
|
||||||
|
// Use state to avoid excessive ensureItemIterator calls.
|
||||||
|
// The state is represented by the integer to avoid an overhead associated with the enum.
|
||||||
|
var state = State.UNDEFINED
|
||||||
|
|
||||||
override fun next(): E {
|
override fun next(): E {
|
||||||
if (!ensureItemIterator())
|
if (state == State.DONE) throw NoSuchElementException()
|
||||||
|
if (state == State.UNDEFINED && !ensureItemIterator()) {
|
||||||
throw NoSuchElementException()
|
throw NoSuchElementException()
|
||||||
|
}
|
||||||
|
state = State.UNDEFINED
|
||||||
return itemIterator!!.next()
|
return itemIterator!!.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
|
if (state == State.READY) return true
|
||||||
|
if (state == State.DONE) return false
|
||||||
return ensureItemIterator()
|
return ensureItemIterator()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ensureItemIterator(): Boolean {
|
private fun ensureItemIterator(): Boolean {
|
||||||
if (itemIterator?.hasNext() == false)
|
val itemIterator = itemIterator
|
||||||
itemIterator = null
|
if (itemIterator != null && itemIterator.hasNext()) {
|
||||||
|
state = State.READY
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
while (itemIterator == null) {
|
while (iterator.hasNext()) {
|
||||||
if (!iterator.hasNext()) {
|
val element = iterator.next()
|
||||||
return false
|
val nextItemIterator = iterator(transformer(element))
|
||||||
} else {
|
if (nextItemIterator.hasNext()) {
|
||||||
val element = iterator.next()
|
this.itemIterator = nextItemIterator
|
||||||
val nextItemIterator = iterator(transformer(element))
|
state = State.READY
|
||||||
if (nextItemIterator.hasNext()) {
|
return true
|
||||||
itemIterator = nextItemIterator
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
|
state = State.DONE
|
||||||
|
this.itemIterator = null
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user