我想以功能方式实现迭代器特征,即不使用var。该怎么做?
假设我有一个外部库,可以在其中通过调用函数getNextElements(numOfElements: Int):Array[String]
得到一些元素,并且我想使用该函数实现一个Iterator,但不使用表示“当前”数组的变量(在我的情况下, var缓冲区)。我该如何以功能性方式实现呢?
class MyIterator[T](fillBuffer: Int => Array[T]) extends Iterator[T] {
var buffer: List[T] = fillBuffer(10).toList
override def hasNext(): Boolean = {
if (buffer.isEmpty) buffer = fillBuffer(10).toList
buffer.nonEmpty
}
override def next(): T = {
if (!hasNext()) throw new NoSuchElementException()
val elem: T = buffer.head
buffer = buffer.tail
elem
}
}
class Main extends App {
def getNextElements(num: Int): Array[String] = ???
val iterator = new MyIterator[String](getNextElements)
iterator.foreach(println)
}
答案 0 :(得分:4)
迭代器是可变的,至少在没有返回状态变量的接口的情况下是可变的,因此,一般来说,如果没有某种形式的突变,就不能直接实现接口。
话虽这么说,Iterator
伴随对象中有一些非常有用的函数,这些函数可让您隐藏突变并简化实现。我会像这样实现您的:
Iterator.continually(getNextElements(10)).flatten
这在需要填充缓冲区时调用getNextElements(10)
。 flatten
将其从Iterator[Array[A]]
更改为Iterator[A]
。
请注意,这将返回一个无限迭代器。您的问题没有说明检测源元素的结尾,但是我通常会使用takeWhile
来实现。例如,如果getNextElements
在没有更多元素时返回空数组,则可以执行以下操作:
Iterator.continually(getNextElements(10)).takeWhile(!_.isEmpty).flatten