Faster filtering and flatmapping iterators
This commit is contained in:
parent
2935b3c2ad
commit
218bb17cc4
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user