de.mrapp.util.IteratorUtil.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-util Show documentation
Show all versions of java-util Show documentation
Contains various utility classes for use in Java development.
The newest version!
/*
* Copyright 2017 - 2019 Michael Rapp
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package de.mrapp.util
import de.mrapp.util.Condition.ensureNotNull
/**
* An utility class that provides methods that allows to handle [Iterator]s and [Iterable]s.
*
* @author Michael Rapp
* @since 2.2.0
*/
object IteratorUtil {
/**
* Creates and returns an [Iterable] that maps the items that are traversed by another
* [iterable] using a specific [mapper].
*
* @param I The type of the items that are traversed by the given [Iterable]
* @param O The type, the items are mapped to
*/
fun createMappedIterable(iterable: Iterable, mapper: (I) -> O): Iterable {
ensureNotNull(iterable, "The iterable may not be null")
ensureNotNull(mapper, "The mapper may not be null")
return Iterable { createMappedIterator(iterable.iterator(), mapper) }
}
/**
* Creates and returns an [Iterator] that maps the items that are traversed by another
* [iterator] using a specific [mapper].
*
* @param I The type of the items that are traversed by the given [Iterator]
* @param O The type, the items are mapped to
*/
fun createMappedIterator(iterator: Iterator, mapper: (I) -> O): Iterator {
ensureNotNull(iterator, "The iterator may not be null")
ensureNotNull(mapper, "The mapper may not be null")
return object : Iterator {
override fun hasNext() = iterator.hasNext()
override fun next() = mapper.invoke(iterator.next())
}
}
/**
* Creates and returns an [Iterable] that allows to traverse the items that are traversed by two
* other [Iterable]s, [first] and [second].
*
* @param T The type of the items that are traversed by the given [Iterable]s
*/
fun createConcatenatedIterable(first: Iterable, second: Iterable): Iterable {
ensureNotNull(first, "The first iterable may not be null")
ensureNotNull(second, "The second iterable may not be null")
return Iterable { createConcatenatedIterator(first.iterator(), second.iterator()) }
}
/**
* Creates and returns an [Iterator] that allows to traverse the items that are traversed by two
* other [Iterator]s, [first] and [second].
*
* @param T The type of the items that are traversed by the given [Iterator]s
*/
fun createConcatenatedIterator(first: Iterator, second: Iterator): Iterator {
ensureNotNull(first, "The first iterator may not be null")
ensureNotNull(second, "The second iterator may not be null")
return object : Iterator {
override fun hasNext() = first.hasNext() || second.hasNext()
override fun next() = try {
first.next()
} catch (e: NoSuchElementException) {
second.next()
}
}
}
/**
* Creates and returns an [Iterable] that allows to traverse the items that are traversed by
* another [iterable] except for the items for which a [filter] returns false.
*
* @param T The type of the items that are traversed by the given [Iterable]
*/
fun createFilteredIterable(iterable: Iterable, filter: (T) -> Boolean): Iterable {
ensureNotNull(iterable, "The iterable may not be null")
ensureNotNull(filter, "The filter may not be null")
return Iterable { createFilteredIterator(iterable.iterator(), filter) }
}
/**
* Creates and returns an [Iterator] that allows to traverse the items that are traversed by
* another [iterator] except for the items for which a [filter] returns false.
*
* @param T The type of the items that are traversed by the given [Iterator]
*/
fun createFilteredIterator(iterator: Iterator, filter: (T) -> Boolean): Iterator {
ensureNotNull(iterator, "The iterator may not be null")
ensureNotNull(filter, "The filter may not be null")
return object : Iterator {
private var hasNext = false
private var next: T? = null
init {
computeNext()
}
private fun computeNext() {
this.hasNext = false
while (iterator.hasNext()) {
val next = iterator.next()
if (filter.invoke(next)) {
this.hasNext = true
this.next = next
return
}
}
}
override fun hasNext() = hasNext
override fun next() = if (hasNext) {
val result = next
computeNext()
result
} else throw NoSuchElementException()
}
}
/**
* Creates and returns an [Iterable] that allows to traverse the items that are traversed by
* another [iterable] except for the items which are null.
*
* @param T The type of the items that are traversed by the given [Iterable]
*/
fun createNotNullIterable(iterable: Iterable): Iterable {
ensureNotNull(iterable, "The iterable may not be null")
return Iterable { createNotNullIterator(iterable.iterator()) }
}
/**
* Creates and returns an [Iterator] that allows to traverse the items that are traversed by
* another [iterator] except for the items which are null.
*
* @param T The type of the items that are traversed by the given [Iterator]
*/
fun createNotNullIterator(iterator: Iterator): Iterator {
ensureNotNull(iterator, "The iterator may not be null")
return object : Iterator {
private var next = computeNext()
private fun computeNext(): T? {
var result: T? = null
while (result == null && iterator.hasNext()) {
val next = iterator.next()
if (next != null) {
result = next
}
}
return result
}
override fun hasNext() = next != null
override fun next() = next?.let {
next = computeNext()
it
} ?: throw NoSuchElementException()
}
}
/**
* Creates and returns an [Iterable] that allows to traverse all items of [Iterator]s that are
* created for each item that is traversed by an [outerIterable] using a [factory].
*
* @param T1 The type of the items that are traversed by the given [Iterable]
* @param T2 The type of the items that should be traversed by the created [Iterable]
*/
fun createNestedIterable(outerIterable: Iterable,
factory: (T1) -> Iterator): Iterable {
ensureNotNull(outerIterable, "The iterable may not be null")
ensureNotNull(factory, "The factory may not be null")
return Iterable { createNestedIterator(outerIterable.iterator(), factory) }
}
/**
* Creates and returns an [Iterator] that allows to traverse all items of [Iterator]s that are
* created for each item that is traversed by an [outerIterator] using a [factory].
*
* @param T1 The type of the items that are traversed by the given [Iterator]
* @param T2 The type of the items that should be traversed by the created [Iterator]
*/
fun createNestedIterator(outerIterator: Iterator,
factory: (T1) -> Iterator): Iterator {
ensureNotNull(outerIterator, "The iterator may not be null")
ensureNotNull(factory, "The factory may not be null")
return object : Iterator {
private var innerIterator: Iterator? = null
private var hasNext = false
private var next: T2? = null
init {
computeNext()
}
private fun computeNext() {
this.hasNext = false
var iterator = innerIterator
while ((iterator != null && iterator.hasNext()) || outerIterator.hasNext()) {
if (iterator != null && iterator.hasNext()) {
this.hasNext = true
this.next = iterator.next()
return
} else {
iterator = factory.invoke(outerIterator.next()).also {
innerIterator = it
}
}
}
}
override fun hasNext() = hasNext
override fun next() = if (hasNext) {
val result = next
computeNext()
result
} else throw NoSuchElementException()
}
}
}