为什么会这样?
我已编写此代码并抛出 java.util.ConcurrentModificationException
List<Integer> list = Stream.iterate(0, t -> t + 1).limit(10).collect(Collectors.toList());
System.out.println(list);
List<Integer> subList = list.subList(5, list.size());
list.removeAll(subList);
System.out.println(subList);
System.out.println(list);
但下一个代码不会抛出
List<Integer> list = Stream.iterate(0, t -> t + 1).limit(10).collect(Collectors.toList());
System.out.println(list);
List<Integer> subList = list.subList(5, list.size());
System.out.println(subList);
list.removeAll(subList);
System.out.println(list);
答案 0 :(得分:4)
查看subList()
方法的Javadoc,它明确指出:
如果是,则此方法返回的列表的语义将变为未定义 支持列表(即,此列表)以任何方式结构修改 除了通过返回的列表。
在您的第一个示例中,这正是发生的事情:您通过调用removeAll()
在结构上修改了支持列表,因此您的子列表的行为现在未指定。
打印列表的后续调用最终会抛出ConcurrentModificationException
,这只是一个实现细节。
如果你想避免这种情况,你必须从你检索的子列表中创建一个新列表,即
List<Integer> subList = new ArrayList<>(list.subList(5, list.size()));
list.removeAll(subList);
现在可以独立访问和修改这两个列表。
答案 1 :(得分:0)
谢谢你,Robby Cornelissen。
下一个代码将修复
List<Integer> subList = new ArrayList<>(list.subList(5, list.size()));
答案 2 :(得分:0)
代替创建新列表,使用CopyOnWriteArrayList
怎么办?
List<Integer> subList = new CopyOnWriteArrayList<>(list.subList(5, list.size()));