如何写一个正确的iterator

咱们知道, iterator 是一个可变对象, 换句话来讲, 它的next方法是有反作用的。
 对于那些由容器产生的iterator来讲, hasNext通常都是没有反作用的。可是, 某些时候, hasNext也是可能有反作用的。举个例子来讲, 若是咱们要基于BufferedReader来写一个能够迭代行的迭代器, 咱们就要在hashNext里面尝试读取新的一行, 因而, 反作用就产生了。 

当咱们的hasNext方法是有反作用的时候, 就要特别当心了。由于用户有可能会连续屡次调用hasNext这个方法!

同时,咱们还要考虑一个问题。 通常状况下, 咱们理想的迭代器使用方法是这样的

if (iter.hasNext) { val v = iter.next; 使用v来作一些事情 } else {退出迭代过程}
if (iter.hasNext) { val v = iter.next; 使用v来作一些事情 } else {退出迭代过程}
if (iter.hasNext) { val v = iter.next; 使用v来作一些事情 } else {退出迭代过程}

...... java


也就是说, 咱们的迭代器的正确性依赖于 hasNext, next, hasNext, next....这个“合理的”调用序列
可是, 事实上, 用户其实并不必定会按照这种正确的调用顺序来使用咱们的迭代器。

为了实现一个可让用户随意安排调用序列, 咱们要让迭代器知足两个性质:
1。任什么时候候, 任意两次连续的hasNext方法, 老是等价于一次hasNext
2。任什么时候候, 任意两次连续的next方法, 都等价于在这两个next方法中间插入一个hasNext方法

所谓的“a等价于b”, 就是说, 不管是经过途径a仍是途径b, iterator最后的内部状态 都是同样的。

 只要同时知足这两个性质, 就能够放心地把iterator的正确性 设计成 依赖于 hasNext, next, hasNext, next....这个“合理的”调用序列 。 curl


能够发现, 对于基于容器(List,Map,Set等等)的iterator来讲, 这两个性质是“自然地, 直接地, 简单地”就知足的。其缘由在于:若是hasNext方法是无反作用的,那么上面的两个性质必定会知足this

可是当咱们要写一些并非基于容器的迭代器的时候, 这时候hasNext方法有可能会有反作用, 咱们就要注意检查是否知足上面两个条件了。 url


总结起来: scala

看成为iterator的编写者的时候: 咱们要尽可能让hasNext没有反作用,若是实在不行,就要注意验证是否是可以知足上面的两个性质.  设计

看成为iterator的使用者的时候: 咱们要假定hasNext是有反作用的, 因此要严格按照hasNext, next ... 这个调用序列来使用别人写的iterator code


最后,给出一个例子, 写一个能够迭代行的迭代器: 对象


import java.io._ def toReader(fp: String, enc: String): Reader = new InputStreamReader(new FileInputStream(new File(fp)), enc) def iLines(reader: Reader): Iterator[String] = { val br = new BufferedReader(reader) var curline = "" var checked = false var checkedRes = false new Iterator[String] { def hasNext: Boolean = { if (checked) return checkedRes checked = true curline = br.readLine() checkedRes = if (curline != null) true else false return checkedRes } def next: String = { if (!checked) this.hasNext checked = false return curline } } } 
相关文章
相关标签/搜索