2010-10-15 69 views
7

我非常喜欢Java中的for-each-loop构造(for(T e : iterable)),它可以在任何Iterable<T>上工作,因为它使得在很多情况下很容易读取和编写代码。Java迭代器和for-each-loop。任何方式来访问基础迭代器?

我想知道,如果有什么办法可以从这样的循环访问基础迭代器。如果我想使用迭代器中的remove(),这可能是强制性的。

回答

17

不,这个for-each-loop的整个点是抽象出底层的迭代器。

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

+1

而且当你声明它时,如果你打算从列表中删除项目,它应该是一个ListIterator。 – 2010-10-15 12:52:19

1

改为使用for循环。

4

不,你不能删除每个循环中的对象。

用这个代替:

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

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

我一般比较喜欢'for'成语而不是'while'成语,因为它保持了迭代器的范围更小。 – dty 2010-10-15 12:26:33

+3

@dty:您希望保持所有变量的范围尽可能窄。但就我而言,代码的可读性是第一位的。我的版本几乎可以像正常的句子一样读取:'迭代器有下一个元素:',而你的看起来很麻烦。所以,如果我们想从这两种方法中获益,那么将代码提取到一个单独的方法是值得的。恕我直言,这是我们能解决这个问题的最好方法。 – Roman 2010-10-15 16:35:26

0

修改数据具有错误感觉到它,只要创建一个新的可迭代(或集合),并添加你要保持它的物品外,其他时间(有点**

+0

你们从未听说过函数式编程 – fringd 2013-05-01 14:42:05

1

如果集合相当小,您可以选择使用该集合的副本进行迭代,如果您希望能够删除元素,那么您将不必采取行动如果你有两个系列。

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

更好的是,Apache CollectionUtils(有可能是谷歌的替代品和替代品)提供filter(java.util.Collection collection, Predicate predicate)。这个例子返回整个列表。您可以存储谓词以供重用。

CollectionUtils.filter(collection, new Predicate(){ 
     boolean evaluate(Object object){return true;} 
    }); 
1

你是正确的,使用迭代器支持从源集合安全地删除对象,通过对迭代器本身调用remove()的能力。这里的要点是避免一个ConcurrentModifiedException,这意味着一个集合在Iterator打开时被修改。有些集合可以让你在迭代时删除或添加元素到集合中,但是在Iterator上调用remove()是一种更安全的做法。

但迭代器支持派生和更强大的表弟的ListIterator,只能从列表,支持添加和迭代过程中从列表中删除,以及通过列表滚动双向。