在 Java 中,您可以在遍历 List 的同时修改它吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20639098/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Java, can you modify a List while iterating through it?
提问by user176410
I understand that in Java a Collection<E>
should not be modified while iterating through it, such as removing or adding elements. But what about changing the elements in a List? For example, what if we have
我知道在 Java 中Collection<E>
迭代时不应修改a ,例如删除或添加元素。但是如何改变 List 中的元素呢?例如,如果我们有
List<String> letters = new ArrayList<String>();
letters.add("A");
letters.add("B");
letters.add("C");
int i = 0;
for (String letter : letters) {
letters.set(i, "D");
i++;
}
So, I'm not talking about modifying the object stored at an element; I'm talking about changing whatthe object is. The size of the List is not being changed, but the object at the index is changing, so technically the List is being modified. My boss claims this code is fine (and it does appear to work), but I still don't think it is correct. Would a different way of doing it, maybe using the set(E e) method of a ListIterator, be better?
所以,我不是在谈论修改存储在元素中的对象;我说的是改变对象是什么。List 的大小没有改变,但索引处的对象正在改变,所以从技术上讲,List 正在被修改。我的老板声称这段代码很好(而且看起来确实有效),但我仍然认为它不正确。一种不同的方法,也许使用 ListIterator 的 set(E e) 方法会更好吗?
采纳答案by óscar López
There is nothing wrong with the idea of modifying an element inside a list while traversing it (don't modify the list itself, that's not recommended), but it can be better expressed like this:
在遍历列表时修改列表中的元素的想法并没有错(不要修改列表本身,这是不推荐的),但可以更好地表达如下:
for (int i = 0; i < letters.size(); i++) {
letters.set(i, "D");
}
At the end the whole list will have the letter "D"
as its content. It's not a good idea to use an enhanced for
loop in this case, you're not using the iteration variable for anything, and besides you can't modify the list's contents using the iteration variable.
最后,整个列表将以该字母"D"
作为其内容。for
在这种情况下使用增强循环不是一个好主意,您没有将迭代变量用于任何事情,而且您不能使用迭代变量修改列表的内容。
Notice that the above snippet is notmodifying the list's structure - meaning: no elements are added or removed and the lists' size remains constant. Simply replacing one element by another doesn't count as a structural modification. Here's the linkto the documentation quoted by @ZouZou in the comments, it states that:
请注意,上面的代码片段没有修改列表的结构 - 意思是:没有添加或删除元素,并且列表的大小保持不变。简单地将一个元素替换为另一个元素不算作结构修改。这是@ZouZou 在评论中引用的文档的链接,它指出:
A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification
结构修改是添加或删除一个或多个元素或显式调整后备数组大小的任何操作;仅仅设置元素的值不是结构修改
回答by ThmHarsh
Use CopyOnWriteArrayList
and if you want to remove it, do the following:
使用CopyOnWriteArrayList
,如果要删除它,请执行以下操作:
for (Iterator<String> it = userList.iterator(); it.hasNext() ;)
{
if (wordsToRemove.contains(word))
{
it.remove();
}
}
回答by Luke
Java 8's stream()
interface provides a great way to update a list in place.
Java 8 的stream()
界面提供了一种很好的方式来更新列表。
To safely update items in the list, use map()
:
要安全地更新列表中的项目,请使用map()
:
List<String> letters = new ArrayList<>();
// add stuff to list
letters = letters.stream().map(x -> "D").collect(Collectors.toList());
To safely remove items in place, use filter()
:
要安全地移除物品,请使用filter()
:
letters.stream().filter(x -> !x.equals("A")).collect(Collectors.toList());