什么是替换For-Each循环进行过滤?

时间:2009-10-01 15:53:53

标签: java list foreach

虽然for-each循环有许多优点,但问题是,当你想要过滤(过滤意味着从列表中删除元素)一个列表时,它不起作用,你能取悦任何替换,因为即使遍历索引也不是不错的选择..

4 个答案:

答案 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。因此,使用上面的循环,代码将按如下方式工作:

  1. hasNext()?是。下一个()。 element指向1st A.
  2. hasNext()?是。下一个()。 element指向第二位。
  3. hasNext()?是。下一个()。 element指向1st B. remove()。迭代器计数器不会改变,它仍然指向B所在的位置(从技术上讲,这不是完全正确的,但从逻辑上讲它是如何工作的)。如果你现在再次调用remove(),你会得到一个异常(因为列表元素不再存在)。
  4. hasNext()?是。下一个()。 element指向第二B.其余与#3
  5. 相同
  6. hasNext()?是。下一个()。 element指向第3位。
  7. hasNext()?不,我们已经完成了。列表现在有3个元素。
  8. 更新#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的方法。

http://commons.apache.org/collections/api-2.1.1/org/apache/commons/collections/CollectionUtils.html#filter(java.util.Collection,%20org.apache.commons.collections.Predicate)

答案 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;