Faster filtering and flatmapping iterators

This commit is contained in:
DBotThePony 2023-08-22 11:35:00 +07:00
parent 2935b3c2ad
commit 218bb17cc4
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -1,11 +1,15 @@
package ru.dbotthepony.mc.otm.core.collect package ru.dbotthepony.mc.otm.core.collect
import it.unimi.dsi.fastutil.ints.Int2IntFunction
import it.unimi.dsi.fastutil.ints.IntIterator
import it.unimi.dsi.fastutil.ints.IntIterators
import it.unimi.dsi.fastutil.objects.ObjectIterators import it.unimi.dsi.fastutil.objects.ObjectIterators
import ru.dbotthepony.mc.otm.core.addAll import ru.dbotthepony.mc.otm.core.addAll
import java.util.Optional import java.util.Optional
import java.util.Spliterator import java.util.Spliterator
import java.util.Spliterators import java.util.Spliterators
import java.util.function.BinaryOperator import java.util.function.BinaryOperator
import java.util.function.IntPredicate
import java.util.function.Predicate import java.util.function.Predicate
import java.util.function.Supplier import java.util.function.Supplier
import java.util.stream.Collector import java.util.stream.Collector
@ -21,68 +25,43 @@ import java.util.stream.StreamSupport
// Aside parallel work, unimplemented Stream API elements can be easily implemented when required // Aside parallel work, unimplemented Stream API elements can be easily implemented when required
/** private class FilteringIterator<T>(private val parent: Iterator<T>, private val predicate: Predicate<in T>) : MutableIterator<T> {
* Filters elements of [parent] iterator private var value: T = parent.next()
* private var hasValue = true
* Resulting [Iterator] is [MutableIterator] if [parent] is
*/
class FilteringIterator<T>(private val parent: Iterator<T>, private val predicate: Predicate<in T>) : MutableIterator<T> {
private var foundValue: Any? = Companion
private var returned = false private var returned = false
override fun hasNext(): Boolean { override fun hasNext(): Boolean {
if (foundValue === Companion) { return hasValue
while (parent.hasNext()) {
val next = parent.next()
if (predicate.test(next)) {
foundValue = next
return true
}
}
return false
}
return true
} }
@Suppress("unchecked_cast")
override fun next(): T { override fun next(): T {
var foundValue = foundValue if (!hasValue) throw NoSuchElementException()
hasValue = false
returned = true
if (foundValue === Companion) { val value = this.value
if (!hasNext()) {
throw NoSuchElementException()
}
foundValue = this.foundValue while (parent.hasNext()) {
val next = parent.next()
if (foundValue === Companion) { if (predicate.test(next)) {
throw ConcurrentModificationException() hasValue = true
this.value = next
break
} }
} }
this.foundValue = Companion return value
returned = true
return foundValue as T
} }
override fun remove() { override fun remove() {
if (!returned) throw NoSuchElementException() if (!returned) throw NoSuchElementException()
(parent as MutableIterator<T>).remove()
returned = false returned = false
(parent as MutableIterator<T>).remove()
} }
private companion object
} }
/** private class MappingIterator<T, R>(private val parent: Iterator<T>, private val mapper: (T) -> R) : MutableIterator<R> {
* Maps elements of [parent] iterator from values of [T] to [R] using function [mapper]
*
* Resulting [Iterator] is [MutableIterator] if [parent] is
*/
class MappingIterator<T, R>(private val parent: Iterator<T>, private val mapper: (T) -> R) : MutableIterator<R> {
override fun hasNext(): Boolean { override fun hasNext(): Boolean {
return parent.hasNext() return parent.hasNext()
} }
@ -96,29 +75,28 @@ class MappingIterator<T, R>(private val parent: Iterator<T>, private val mapper:
} }
} }
/** private class FlatMappingIterator<T, R>(private val parent: Iterator<T>, private val mapper: (T) -> Iterator<R>) : MutableIterator<R> {
* Maps elements of [parent] iterator from type [T] to other iterators of type [R] using function [mapper] private var current: Iterator<R> = mapper.invoke(parent.next())
*
* Resulting [Iterator] is [MutableIterator] if [parent] is
*/
class FlatMappingIterator<T, R>(private val parent: Iterator<T>, private val mapper: (T) -> Iterator<R>) : MutableIterator<R> {
private var current: Iterator<R>? = null
private var last: Iterator<R>? = null private var last: Iterator<R>? = null
private var hasNext = current.hasNext()
override fun hasNext(): Boolean { override fun hasNext(): Boolean {
while (current?.hasNext() != true && parent.hasNext()) { return hasNext
current = mapper.invoke(parent.next())
}
return current?.hasNext() == true
} }
override fun next(): R { override fun next(): R {
if (!hasNext()) if (!hasNext)
throw NoSuchElementException() throw NoSuchElementException()
val v = current!!.next() val v = current.next()
last = current last = current
hasNext = false
while (!hasNext && parent.hasNext()) {
current = mapper.invoke(parent.next())
hasNext = current.hasNext()
}
return v return v
} }
@ -128,12 +106,7 @@ class FlatMappingIterator<T, R>(private val parent: Iterator<T>, private val map
} }
} }
/** private class LimitingIterator<T>(private val parent: Iterator<T>, private val limit: Long) : Iterator<T> {
* Limits amount of values returned by [parent] iterator to return at most [limit] values
*
* Resulting [Iterator] is [MutableIterator] if [parent] is
*/
class LimitingIterator<T>(private val parent: Iterator<T>, private val limit: Long) : Iterator<T> {
init { init {
require(limit > 0) { "Invalid limit $limit" } require(limit > 0) { "Invalid limit $limit" }
} }
@ -152,12 +125,7 @@ class LimitingIterator<T>(private val parent: Iterator<T>, private val limit: Lo
} }
} }
/** private class SkippingIterator<T>(private val parent: Iterator<T>, skip: Long) : MutableIterator<T> {
* Skips (discards) up to [skip] values returned by [parent] iterator
*
* Resulting [Iterator] is [MutableIterator] if [parent] is
*/
class SkippingIterator<T>(private val parent: Iterator<T>, skip: Long) : MutableIterator<T> {
init { init {
require(skip >= 0) { "Invalid skip amount $skip" } require(skip >= 0) { "Invalid skip amount $skip" }
} }
@ -214,71 +182,92 @@ fun <T> concatIterators(vararg iterators: Iterator<T>): MutableIterator<T> {
* *
* Resulting [Iterator] is [MutableIterator] if [this] is * Resulting [Iterator] is [MutableIterator] if [this] is
*/ */
fun <T> Iterator<T>.filter(condition: Predicate<in T>) = FilteringIterator(this, condition) fun <T> Iterator<T>.filter(condition: Predicate<in T>): MutableIterator<T> {
if (!hasNext()) {
return emptyIterator()
}
return FilteringIterator(this, condition)
}
/** /**
* Maps elements of [this] iterator from values of [T] to [R] using function [mapper] * Maps elements of [this] iterator from values of [T] to [R] using function [mapper]
* *
* Resulting [Iterator] is [MutableIterator] if [this] is * Resulting [Iterator] is [MutableIterator] if [this] is
*/ */
fun <T, R> Iterator<T>.map(mapper: (T) -> R) = MappingIterator(this, mapper) fun <T, R> Iterator<T>.map(mapper: (T) -> R): MutableIterator<R> {
if (!hasNext()) {
return emptyIterator()
}
/** return MappingIterator(this, mapper)
* Maps elements of [this] iterator from values of [T] to [R] using function [mapper] }
*
* Resulting [Iterator] is [MutableIterator] if [this] is
*/
fun <T, R> Iterator<T>.map(mapper: java.util.function.Function<T, R>) = MappingIterator(this, mapper::apply)
/** /**
* Maps elements of [this] iterator from type [T] to other iterators of type [R] using function [mapper] * Maps elements of [this] iterator from type [T] to other iterators of type [R] using function [mapper]
* *
* Resulting [Iterator] is [MutableIterator] if [this] is * Resulting [Iterator] is [MutableIterator] if [this] is
*/ */
fun <T, R> Iterator<T>.flatMap(mapper: (T) -> Iterator<R>) = FlatMappingIterator(this, mapper) fun <T, R> Iterator<T>.flatMap(mapper: (T) -> Iterator<R>): MutableIterator<R> {
if (!hasNext()) {
return emptyIterator()
}
/** return FlatMappingIterator(this, mapper)
* Maps elements of [this] iterator from type [T] to other iterators of type [R] using function [mapper] }
*
* Resulting [Iterator] is [MutableIterator] if [this] is
*/
fun <T, R> Iterator<T>.flatMap(mapper: java.util.function.Function<T, Iterator<R>>) = FlatMappingIterator(this, mapper::apply)
fun <T> Iterator<T>.reduce(identity: T, reducer: (T, T) -> T): T { inline fun <T> Iterator<T>.reduce(identity: T, reducer: (T, T) -> T): T {
var result = identity var result = identity
for (value in this) result = reducer.invoke(result, value) while (hasNext()) result = reducer.invoke(result, next())
return result return result
} }
fun <T> Iterator<T>.reduce(identity: T, reducer: BinaryOperator<T>): T = reduce(identity, reducer::apply)
fun <T> Iterator<T?>.filterNotNull(): MutableIterator<T> = filter { it != null } as MutableIterator<T> fun <T> Iterator<T?>.filterNotNull(): MutableIterator<T> = filter { it != null } as MutableIterator<T>
fun <T> Iterator<T>.any(predicate: Predicate<in T>): Boolean { fun <T> Iterator<T>.any(predicate: Predicate<in T>): Boolean {
for (value in this) { while (hasNext())
if (predicate.test(value)) { if (predicate.test(next()))
return true
return false
}
inline fun <T> Iterator<T>.any(predicate: (T) -> Boolean): Boolean {
while (hasNext())
if (predicate.invoke(next()))
return true return true
}
}
return false return false
} }
fun <T> Iterator<T>.all(predicate: Predicate<in T>): Boolean { fun <T> Iterator<T>.all(predicate: Predicate<in T>): Boolean {
for (value in this) { while (hasNext())
if (!predicate.test(value)) { if (!predicate.test(next()))
return false
return true
}
inline fun <T> Iterator<T>.all(predicate: (T) -> Boolean): Boolean {
while (hasNext())
if (!predicate.invoke(next()))
return false return false
}
}
return true return true
} }
fun <T> Iterator<T>.none(predicate: Predicate<in T>): Boolean { fun <T> Iterator<T>.none(predicate: Predicate<in T>): Boolean {
for (value in this) { while (hasNext())
if (predicate.test(value)) { if (predicate.test(next()))
return false
return true
}
inline fun <T> Iterator<T>.none(predicate: (T) -> Boolean): Boolean {
while (hasNext())
if (predicate.invoke(next()))
return false return false
}
}
return true return true
} }
@ -308,8 +297,8 @@ fun <T : Any> Iterator<T>.find(): Optional<T> {
return Optional.empty<T>() return Optional.empty<T>()
} }
fun <T> Iterator<T>.limit(limit: Long) = LimitingIterator(this, limit) fun <T> Iterator<T>.limit(limit: Long): Iterator<T> = LimitingIterator(this, limit)
fun <T> Iterator<T>.skip(skip: Long) = if (skip == 0L) this else SkippingIterator(this, skip) fun <T> Iterator<T>.skip(skip: Long): Iterator<T> = if (skip == 0L) this else SkippingIterator(this, skip)
inline fun <T> Iterator<T>.forEach(action: (T) -> Unit) { inline fun <T> Iterator<T>.forEach(action: (T) -> Unit) {
for (value in this) { for (value in this) {