我试图使用迭代器中的迭代次数作为计数器,但是想知道这样做的后果.
private int length(Iterator<?> it) {
int i = 0;
while(it.hasNext()) {
it.next();
i++;
}
return i;
}
Run Code Online (Sandbox Code Playgroud)
这工作正常,但我担心迭代器可能在幕后做什么.也许当我迭代堆栈时,它会弹出堆栈中的项目,或者如果我使用优先级队列,它会修改优先级.
关于迭代器的javadoc说这个:
next
E next()
返回迭代中的下一个元素.
返回:
迭代中的下一个元素
抛出:
NoSuchElementException - 如果迭代没有更多元素
我没有看到保证迭代这个未知的集合不会修改它.我是在考虑不切实际的边缘情况,还是这是一个问题?有没有更好的办法?
在Iterator简单地提供了一个接口转换成某种流的,因此它不仅是完全有可能next()以某种方式破坏数据,但它甚至可以将数据在Iterator是唯一的,不可替代的.
我们可以拿出更多的直接的例子,但一个简单的一种是Iterator在DirectoryStream.虽然在DirectoryStream技术上Iterable,它只允许Iterator构造一个,所以如果你试图做以下事情:
Path dir = ...
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
int count = length(stream.iterator());
for (Path entry: stream) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
您将在foreach块中获得异常,因为流只能迭代一次.总而言之,您的length()方法可能会更改对象并丢失数据.
此外,没有理由Iterator必须与某个单独的数据存储相关联.以我几个月前给出的答案为例,提供一种选择n随机数的简洁方法.通过使用无限,Iterator我们能够懒惰地提供,过滤和传递任意大量的随机数据,无需一次性存储,甚至计算它们直到需要它们.因为Iterator它不支持任何数据结构,所以查询它显然具有破坏性.
既然如此,这些例子并没有使你的方法变坏.请注意,Guava库(每个人都应该使用)提供了一个Iterators类,其中包含您在上面详述的行为,称为size()符合Collections Framework.然后,这些方法的用户需要知道他们正在使用什么类型的数据,并避免进行不小心的调用,例如尝试计算Iterator他们知道无法替换的结果数量.