我理解在Java中,Collection<E>
在迭代它时不应该被修改,例如删除或添加元素。但是如何更改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++;
}
所以,我不是在谈论修改存储在元素中的对象;我在谈论改变对象是什么。 List的大小没有改变,但索引处的对象正在改变,所以从技术上讲,List正在被修改。我的老板声称这段代码很好(而且看起来确实有效),但我仍然认为它不正确。使用ListIterator的set(E e)方法做一个不同的方法会更好吗?
答案 0 :(得分:37)
在遍历它时修改列表中的元素的想法没有任何问题(不要修改列表本身,不建议这样做),但它可以更好地表达如下:
for (int i = 0; i < letters.size(); i++) {
letters.set(i, "D");
}
最后,整个列表将以"D"
字母作为其内容。在这种情况下使用增强的for
循环并不是一个好主意,你没有将迭代变量用于任何东西,而且你不能使用迭代变量修改列表的内容。
请注意,上面的代码段不修改列表的结构 - 意思是:没有添加或删除元素,列表的大小保持不变。简单地将一个元素替换为另一个元素并不算作结构修改。以下是@ZouZou在评论中引用的文档的link,它声明:
结构修改是添加或删除一个或多个元素或显式调整后备数组大小的任何操作;仅设置元素的值不是结构修改
答案 1 :(得分:12)
使用CopyOnWriteArrayList
如果要删除它,请执行以下操作:
for (Iterator<String> it = userList.iterator(); it.hasNext() ;)
{
if (wordsToRemove.contains(word))
{
it.remove();
}
}
答案 2 :(得分:1)
答案 3 :(得分:0)
Java 8的stream()
接口提供了一种在适当位置更新列表的好方法。
要安全地更新列表中的项目,请使用map()
:
List<String> letters = new ArrayList<>();
// add stuff to list
letters = letters.stream().map(x -> "D").collect(Collectors.toList());
要安全地移除适当的项目,请使用filter()
:
letters.stream().filter(x -> !x.equals("A")).collect(Collectors.toList());