概述
2019独角兽企业重金招聘Python工程师标准>>>
对于那些由容器产生的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 {退出迭代过程}
......
也就是说, 我们的迭代器的正确性依赖于 hasNext, next, hasNext, next....这个“合理的”调用序列
但是, 事实上, 用户其实并不一定会按照这种正确的调用顺序来使用我们的迭代器。
为了实现一个可以让用户随意安排调用序列, 我们要让迭代器满足两个性质:
1。任何时候, 任意两次连续的hasNext方法, 总是等价于一次hasNext
2。任何时候, 任意两次连续的next方法, 都等价于在这两个next方法中间插入一个hasNext方法
所谓的“a等价于b”, 就是说, 无论是通过途径a还是途径b, iterator最后的内部状态 都是一样的。
只要同时满足这两个性质, 就可以放心地把iterator的正确性 设计成 依赖于 hasNext, next, hasNext, next....这个“合理的”调用序列 。
可以发现, 对于基于容器(List,Map,Set等等)的iterator来说, 这两个性质是“天然地, 直接地, 简单地”就满足的。其原因在于:如果hasNext方法是无副作用的,那么上面的两个性质一定会满足。
但是当我们要写一些并不是基于容器的迭代器的时候, 这时候hasNext方法有可能会有副作用, 我们就要注意检查是否满足上面两个条件了。
总结起来:
当作为iterator的编写者的时候: 我们要尽量让hasNext没有副作用,如果实在不行,就要注意验证是不是能够满足上面的两个性质.
当作为iterator的使用者的时候: 我们要假定hasNext是有副作用的, 所以要严格按照hasNext, next ... 这个调用序列来使用别人写的iterator
最后,给出一个例子, 写一个可以迭代行的迭代器:
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
}
}
}
转载于:https://my.oschina.net/mustang/blog/91547
最后
以上就是故意外套为你收集整理的如何写一个正确的iterator的全部内容,希望文章能够帮你解决如何写一个正确的iterator所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复