Java迭代器和for-each循环。有没有一种方法可以访问底层迭代器?

8

我非常喜欢Java中的for-each循环结构(for(T e : iterable)),它适用于任何Iterable<T>,因为它使得在许多情况下编写和阅读代码变得非常容易。

但是我想知道是否有办法从这样的循环中访问底层的迭代器。如果我想使用迭代器的remove()方法,这可能是必需的。

6个回答

17

不,for-each循环的整个重点在于抽象化底层迭代器。

如果你需要它,你必须声明它。


1
当你声明它时,如果你计划从列表中删除项目,它应该是一个ListIterator。 - Jack Cox

4

不,你不能在for each循环中删除对象。

应该使用以下方式代替:

Iterator<Type> it = collection.iterator();

while (it.hasNext()) {
   if (it.next().shouldBeRemoved()) {
       it.remove();
   }
}

3
我通常更喜欢使用 for 循环而不是 while 循环,因为它可以使迭代器的作用域更小。 - dty
3
你的想法要尽可能地缩小所有变量作用域是有道理的,但对于我来说,代码可读性排在第一位。我的版本几乎可以像正常的句子一样阅读:'当迭代器有下一个元素时,执行以下操作:...',而你的版本似乎非常繁琐。因此,如果我们想从两种方法中获得好处,值得将我的代码提取到一个单独的方法中。在我看来,这是我们在这个问题上能做的最好的事情。 - Roman

1

如果集合比较小,您可以选择使用集合的副本来进行迭代,这样如果您想要删除元素,就不必像拥有两个集合一样操作。

for(T e : collection.clone())
    if(e.shouldBeRemoved())
        collection.remove();

更好的是,Apache CollectionUtils(可能还有Google的替代品和泛型的替代品)提供了filter(java.util.Collection collection,Predicate predicate)。此示例返回整个列表。您可以存储可重用的谓词。
CollectionUtils.filter(collection, new Predicate(){
        boolean evaluate(Object object){return true;}
    });

1
请使用for循环代替。

1

你是正确的,使用迭代器支持通过在迭代器本身上调用remove()方法,从源集合中安全地删除对象。这里的重点是避免ConcurrentModifiedException,这意味着在打开迭代器时修改了集合。一些集合将允许您在迭代过程中删除或添加元素到集合中,但在迭代器上调用remove()方法是更安全的做法。

但是,迭代器支持一个派生且更强大的表亲ListIterator,仅适用于列表,支持在迭代过程中从列表中添加和删除,以及双向滚动列表。


0
修改数据感觉上有些“不对劲”,最好的方法是创建一个新的Iterable(或集合),并将您想要保留的项目添加到其中,其他的则在for循环中丢失。

你们从未听说过函数式编程。 - fringd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接