为什么这段代码没有抛出ConcurrentModificationException?它修改了一段Collection时间迭代它,而不使用Iterator.remove()方法,这是唯一安全的删除方法.
List<String> strings = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String string : strings)
if ("B".equals(string))
strings.remove("B");
System.out.println(strings);
Run Code Online (Sandbox Code Playgroud)
如果我ArrayList用a 替换,我会得到相同的结果LinkedList.但是,如果我将列表更改为("A", "B", "C", "D)或只是("A", "B")按预期获得异常.到底是怎么回事?我正在使用,jdk1.8.0_25如果这是相关的.
编辑
我找到了以下链接
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4902078
相关部分是
天真的解决方案是在AbstractList中为hasNext添加编码检查,但这会使编纂检查的成本增加一倍.事实证明,仅在最后一次迭代时进行测试就足够了,这几乎不会增加成本.换句话说,hasNext的当前实现:
Run Code Online (Sandbox Code Playgroud)public boolean hasNext() { return nextIndex() < size; }被此实现取代:
Run Code Online (Sandbox Code Playgroud)public boolean hasNext() { if (cursor != size()) return true; checkForComodification(); return false; }由于Sun内部监管机构拒绝了此项更改,因此不会进行此更改.正式裁决表明,这一变化"已证明可能对现有代码产生重大的兼容性影响." ("兼容性影响"是修复程序有可能用ConcurrentModificationException替换静默不当行为.)
以下Java代码ConcurrentModificationException按预期抛出:
public class Evil
{
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("lalala");
c.add("sososo");
c.add("ahaaha");
removeLalala(c);
System.err.println(c);
}
private static void removeLalala(Collection<String> c)
{
for (Iterator<String> i = c.iterator(); i.hasNext();) {
String s = i.next();
if(s.equals("lalala")) {
c.remove(s);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是下面的示例(仅在内容中有所不同)Collection执行时没有任何异常:
public class Evil {
public static void main(String[] args)
{
Collection<String> c = new ArrayList<String>();
c.add("lalala");
c.add("lalala");
removeLalala(c);
System.err.println(c);
}
private static void removeLalala(Collection<String> c) {
for (Iterator<String> i …Run Code Online (Sandbox Code Playgroud) 我有下面的代码,我希望它抛出一个ConcurrentModificationException,但它运行成功.为什么会这样?
public void fun(){
List <Integer>lis = new ArrayList<Integer>();
lis.add(1);
lis.add(2);
for(Integer st:lis){
lis.remove(1);
System.out.println(lis.size());
}
}
public static void main(String[] args) {
test t = new test();
t.fun();
}
Run Code Online (Sandbox Code Playgroud) 我正在阅读有关ConcurrentModificationException以及如何避免它的内容.找到一篇文章.该文章中的第一个列表的代码类似于以下内容,这显然会导致异常:
List<String> myList = new ArrayList<String>();
myList.add("January");
myList.add("February");
myList.add("March");
Iterator<String> it = myList.iterator();
while(it.hasNext())
{
String item = it.next();
if("February".equals(item))
{
myList.remove(item);
}
}
for (String item : myList)
{
System.out.println(item);
}
Run Code Online (Sandbox Code Playgroud)
然后它继续解释如何用各种建议解决问题.
当我试图重现它时,我没有得到例外!为什么我没有得到例外?
我有一个非常基本的问题.
我创建简单ArrayList,我正在使用for-each循环迭代时删除项目.它给了我,java.util.ConcurrentModificationException因为我不能在迭代时if删除一个项目,但是当我取消注释条件时它工作正常.
请任何人都能解释我这样做的方式.
ArrayList<String> list1 = new ArrayList<String>();
list1.add("Hello");
list1.add("World");
list1.add("Good Evening");
for (String s : list1) {
//if (s.equals("World")) {
list1.remove(1);
//}
}
Run Code Online (Sandbox Code Playgroud)
如果我将其更改为list1.remove(2);或者list1.remove(0);其工作正常.
注意:这是示例代码,我知道它可以正常使用Iterator.这个问题的唯一目的是知道remove()如果条件未被注释,无论您从列表中删除什么索引,方法如何完美地工作.
很明显,这段代码在迭代期间修改了一个列表.
public class ArrayIterator {
public static void main(String[] args) {
List<String> list = new LinkedList<>(Arrays.asList("A","B","C","D","E"));
Iterator<String> it = list.iterator();
while (it.hasNext())
{
list.remove(it.next());
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以我们得到了预期的例外
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
at java.util.LinkedList$ListItr.next(LinkedList.java:888)
at ArrayIterator.main(ArrayIterator.java:15)
Run Code Online (Sandbox Code Playgroud)
为什么编译器不能对此发出警告?