迭代器可以更改要迭代的集合吗?爪哇 [英] Can a iterator change the collection it is iterating over? Java

查看:101
本文介绍了迭代器可以更改要迭代的集合吗?爪哇的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正尝试将迭代器的迭代次数用作计数器,但想知道这样做的后果.

I'm attempting to use the number of iterations from an iterator as a counter, but was wondering the ramifications of doing so.

private int length(Iterator<?> it) {
    int i = 0;

    while(it.hasNext()) {
        it.next();
        i++;
    }

    return i;
}

这很好,但是我担心迭代器在后台可能会做什么.也许当我遍历堆栈时,它会将项目弹出堆栈,或者如果我使用优先级队列,它会修改优先级.

This works fine, but I'm worried about what the iterator may do behind the scenes. Perhaps as I'm iterating over a stack, it pops the items off the stack, or if I'm using a priority queue, and it modifies the priority.

javadoc所说的关于迭代器的内容:

The javadoc say this about iterator:

下一个
E next()
返回迭代中的下一个元素.
返回:
迭代中的下一个元素
抛出:
NoSuchElementException-如果迭代中没有更多元素

next
E next()
Returns the next element in the iteration.
Returns:
the next element in the iteration
Throws:
NoSuchElementException - if the iteration has no more elements

我看不到对这个未知集合进行迭代不会对其进行修改的保证.我是否在考虑不切实际的边缘情况,或者这是一个问题?有更好的方法吗?

I don't see a guarantee that iterating over this unknown collection won't modify it. Am I thinking of unrealistic edge cases, or is this a concern? Is there a better way?

推荐答案

Iterator只是提供了某种流接口,因此next()完全有可能以某种方式破坏数据,而且Iterator中的数据甚至可能是唯一且不可替代的.

The Iterator simply provides an interface into some sort of stream, therefore not only is it perfectly possible for next() to destroy data in some way, but it's even possible for the data in an Iterator to be unique and irreplaceable.

我们可以拿出更直接的例子,但是一个简单的例子是

We could come up with more direct examples, but an easy one is the Iterator in DirectoryStream. While a DirectoryStream is technically Iterable, it only allows one Iterator to be constructed, so if you tried to do the following:

Path dir = ...
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
  int count = length(stream.iterator());
  for (Path entry: stream) {
    ...
  }
}

您将在foreach块中获得一个异常,因为该流只能被迭代一次.因此,总而言之,您的length()方法可以更改对象并丢失数据.

You would get an exception in the foreach block, because the stream can only be iterated once. So in summary, it is possible for your length() method to change objects and lose data.

此外,没有理由将Iterator与某些单独的数据存储相关联.例如,我几个月前给出的答案,提供了一种干净的方法来选择n随机数.通过使用无限Iterator,我们可以懒惰地提供,过滤和传递任意数量的随机数据,无需一次存储所有数据,甚至无需计算就可以使用它们.因为Iterator不支持任何数据结构,所以查询它显然是破坏性的.

Furthermore, there's no reason an Iterator has to be associated with some separate data-store. Take for example an answer I gave a few months ago providing a clean way to select n random numbers. By using an infinite Iterator we are able to provide, filter, and pass around arbitrarily large amounts of random data lazily, no need to store it all at once, or even compute them until they're needed. Because the Iterator doesn't back any data structure, querying it is obviously destructive.

现在,这些示例不会使您的方法变坏.请注意, Guava库(每个人都应该使用)提供了 Iterators 类具有您上面详细描述的行为,称为

Now that said, these examples don't make your method bad. Notice that the Guava library (which everyone should be using) provides an Iterators class with exactly the behavior you detail above, called size() to conform with the Collections Framework. The burden is then on the user of such methods to be aware of what sort of data they're working with, and avoid making careless calls such as trying to count the number of results in an Iterator that they know cannot be replaced.

这篇关于迭代器可以更改要迭代的集合吗?爪哇的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆