虽然for-each循环有许多优点,但问题是,当你想要过滤(过滤意味着从列表中删除元素)一个列表时,它不起作用,你能取悦任何替换,因为即使遍历索引也不是不错的选择..
答案 0 :(得分:11)
“过滤”是什么意思?从列表中删除某些元素?如果是这样,您可以使用iterator:
for(Iterator<MyElement> it = list.iterator(); it.hasNext(); ) {
MyElement element = it.next();
if (some condition) {
it.remove();
}
}
更新(根据评论):
请考虑以下示例来说明迭代器的工作原理。假设我们有一个包含'A'和'B'的列表:
A A B B A
我们要删除所有那些讨厌的B
。因此,使用上面的循环,代码将按如下方式工作:
element
指向1st A. element
指向第二位。element
指向1st B. remove()。迭代器计数器不会改变,它仍然指向B所在的位置(从技术上讲,这不是完全正确的,但从逻辑上讲它是如何工作的)。如果你现在再次调用remove(),你会得到一个异常(因为列表元素不再存在)。element
指向第二B.其余与#3 element
指向第3位。 更新#2 :remove()
操作在迭代器上确实是可选的 - 但仅仅因为它在底层集合上是可选的。这里的底线是 - 如果您的集合支持它(以及Java Collection Framework中的所有集合),迭代器也是如此。如果你的收藏品不支持它,那你就不幸了。
答案 1 :(得分:0)
ChssPly76的回答是正确的方法 - 但我对你的想法感到好奇“遍历索引并不是一个好选择”。在许多情况下 - 特别是ArrayList
的常见情况 - 它非常有效。 (事实上,在arraylist案例中,我认为对get(i++)
的重复调用比使用迭代器稍快一些,尽管远远不足以牺牲可读性。)
一般来说,如果有问题的对象实现了java.util.RandomAccess,那么通过索引访问顺序元素应该与使用迭代器的速度大致相同。如果没有(例如LinkedList
将是一个好的反例)那么你是对的;但不要忽视这个选项。
答案 2 :(得分:0)
我使用
取得了成功filter(java.util.Collection collection, Predicate predicate)
公共集合中CollectionUtils的方法。
答案 3 :(得分:0)
如果你像我一样,在迭代它的元素时不喜欢修改集合,或者如果迭代器没有提供删除的实现,你可以使用临时集合来收集你想要删除的元素。是的,是的,与修改迭代器相比效率较低,但对我而言,理解发生的事情更为清楚:
List<Object> data = getListFromSomewhere();
List<Object> filter = new ArrayList<Object>();
// create Filter
for (Object item: data) {
if (throwAway(item)) {
filter.add(item);
}
}
// use Filter
for (Object item:filter) {
data.remove(item);
}
filter.clear();
filter = null;