added a helper method to filter a subset of an iterator by sub type

This commit is contained in:
James Strachan
2012-03-23 11:03:38 +00:00
parent 4a3d0133f6
commit c0cac21b8a
2 changed files with 92 additions and 0 deletions
+20
View File
@@ -1,5 +1,7 @@
package kotlin.util
import kotlin.support.AbstractIterator
import java.util.*
import java.util.Iterator
@@ -24,3 +26,21 @@ inline fun <T> java.util.Iterator<T>.toLinkedHashSet() = to(LinkedHashSet<T>())
/** Add iterated elements to java.util.TreeSet */
inline fun <T> java.util.Iterator<T>.toTreeSet() = to(TreeSet<T>())
/** Filters the iterator for all elements of a certain kind */
inline fun <T, R: T> java.util.Iterator<T>.filterIs(): Iterator<R> {
val iter = this
return object : AbstractIterator<R>() {
override fun computeNext(): R? {
while (iter.hasNext()) {
val next = iter.next()
if (next is R) {
return next as R
}
}
done()
return null
}
}
}
@@ -0,0 +1,72 @@
package kotlin.support
import java.util.*
// TODO should we use enums?
private val Ready = 0
private val NotReady = 1
private val Done = 2
private val Failed = 3
/**
* A base class to simplify implementing iterators so that implementations only have to implement [[#computeNext()]]
* to implement the iterator, calling [[done()]] when the iteration is complete.
*/
abstract class AbstractIterator<T>: Iterator<T> {
var state = NotReady
var next: T? = null
override fun hasNext(): Boolean {
require(state != Failed)
return when (state) {
Done -> false
Ready -> true
else -> tryToComputeNext()
}
}
override fun next(): T {
if (!hasNext()) {
throw NoSuchElementException();
} else {
state = NotReady
return next.sure()
}
}
override fun remove() {
throw UnsupportedOperationException()
}
/**
* Returns the next element in the iteration without advancing the iteration
*/
fun peek(): T {
if (!hasNext()) {
throw NoSuchElementException();
}
return next.sure();
}
private fun tryToComputeNext(): Boolean {
state = Failed
next = computeNext();
return if (state != Done) {
state = Ready
true
} else false
}
/**
* Computes the next element in the iterator, calling endOfData() when
* there are no more elements
*/
abstract protected fun computeNext(): T?
/**
* Sets the state to done so that the iteration terminates
*/
protected fun done() {
state = Done
}
}