使用删除在列表上循环[重复]
Posted
技术标签:
【中文标题】使用删除在列表上循环[重复]【英文标题】:loop on list with remove [duplicate] 【发布时间】:2010-12-27 15:00:38 【问题描述】: for (String fruit : list)
if("banane".equals(fruit))
list.remove(fruit);
System.out.println(fruit);
这里有一个带有删除指令的循环。 在执行时,我在控制台输出下方得到了一些 ConcurrentModificationException:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449)
at java.util.AbstractList$Itr.next(AbstractList.java:420)
at Boucle.main(Boucle.java:14)
abricot
banane
问题:如何使用循环删除某些元素?
【问题讨论】:
【参考方案1】:您需要直接使用迭代器,并通过该迭代器删除项目。
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); )
String fruit = iterator.next();
if ("banane".equals(fruit))
iterator.remove();
System.out.println(fruit);
【讨论】:
对于那些会认出自己的人:不要使用增量索引和 list.size() !我想用 foreach 循环更改代码,但这不是正确的解决方案。你的就是那个。 只需将it.hasNext()
更改为iterator.hasNext()
就完美了! (很明显......但谁知道......)【参考方案2】:
这似乎有点复杂,为什么不做一个普通的for循环呢?我认为它看起来更干净,不会抛出这个错误。如果您删除某些内容,只需贬低 i 即可。至少我的作品,无论如何。我想,这类自动循环更多是为了编码方便,所以如果它们不方便,那就不要使用它们。
for (int i = list.size() - 1; i>=0; i--)
String fruit = list.get(i);
System.out.println(fruit);
if ("banane".equals(fruit))
list.remove(fruit);
【讨论】:
这在大列表上会非常慢(算法术语中的O(n^2)
),因为List#remove(Object)
需要通过对给定对象的列表执行线性搜索来重做工作。如果可能,最好使用索引,这将使它成为O(n)
时间。【参考方案3】:
除了直接使用Iterator
(我会推荐)之外,您还可以将要删除的元素存储在不同的列表中。
List<String> toRemove = new ArrayList<String>();
for (String fruit : list)
if ("banane".equals(fruit))
toRemove.add(fruit);
System.out.println(fruit);
for (String fruit : toRemove)
list.remove(fruit);
请注意,我不建议这样做,这只是一种选择。 :)
【讨论】:
是的。这就是为什么我会使用基于Iterator
的解决方案——这就是我所写的。
有不止一种方法可以做到,但大多数方法都是错误的;)
“错误”也有不止一种含义。 :)【参考方案4】:
使用 for 循环,并以相反的顺序遍历集合。 (这意味着,从最后一个元素开始,然后循环到第一个元素。 通过这样做,您不会因为从集合中删除元素而更改索引而遇到问题。
您在发布的示例中遇到异常,因为您的迭代器迭代的列表已更改,这意味着迭代器变得无效。
【讨论】:
听起来很危险。内存不连续的双向链表之类的呢?我不知道lists et al在Java中是否有index
,或者iterator
是如何实现的,但是如果它像C++一样,如果你的方法适用于除ArrayList
之外的任何东西,我会感到惊讶。【参考方案5】:
for(Iterator<String> iter = list.iterator(); iter.hasNext(); )
String fruit = iter.next();
if("banana".equals(fruit))
iter.remove();
System.out.println(fruit);
【讨论】:
【参考方案6】:类似于 Bombe 的建议,但通过迭代列表副本,但从原始列表中删除,代码行数更少;
List<String> temp = new ArrayList<String>(list);
for (String fruit : temp)
if("banane".equals(fruit))
list.remove(fruit);
System.out.println(fruit);
我个人认为这看起来比使用迭代器进行迭代更好。
【讨论】:
我会说这很容易出错.. 有 2 个列表,我们不需要第二个。只是我的 2 美分。 @cheekoo,我可以看到它会如何使用不必要的内存,但我看不出有能力的开发人员会如何使用这种方法引入错误。 哈哈!我同意。但是现在您已经开始使用条件语句了! “有能力的开发人员”;) 这有不必要的迭代。new ArrayList(list)
将遍历 list
。然后使用for
循环再次对其进行迭代。【参考方案7】:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
Iterator<String> iter = list.iterator();
while (iter.hasNext())
String s = iter.next();
if (s.equals("a"))
iter.remove();
是最好的方法..
【讨论】:
以上是关于使用删除在列表上循环[重复]的主要内容,如果未能解决你的问题,请参考以下文章
Python3基础 list 使用for循环 删除列表中的重复项