我正在通过ConcurrentHashMap搜索Concurrent Set实现,并发现了一些奇怪的东西。 我的代码:
Set<String> keySetView = ConcurrentHashMap.newKeySet();
keySetView.add("1");
keySetView.add("2");
keySetView.add("3");
ArrayList<String> arr = new ArrayList<>(Arrays.asList("1","2","3"));
for (String a : keySetView){
System.out.println("keySetView value = " + a);
keySetView.removeAll(arr);
System.out.println("keySetView after remove size = " + keySetView.size());
}
预期结果:
keySetView value = 1
keySetView after remove size = 0
但是当我运行代码时:
keySetView value = 1
keySetView after remove size = 0
keySetView value = 2
keySetView after remove size = 0
为什么我们已经删除了Set中的所有元素,它仍然显示元素2
答案 0 :(得分:0)
这是因为foreach
循环是通过迭代器实现的,迭代器在第一次循环迭代提取第一个值之后已经指向下一个值。因此,当您调用removeAll时,迭代器已经具有下一个值。现在这是最可能的原因,然而,这是一个永远不能依赖的JVM实现细节,因为它不能保证另一个实现,例如OpenJDK vs OracleJDK不会对foreach
循环使用某种优化。迭代删除元素的唯一安全方法是显式使用迭代器:
Iterator<T> it = set.iterator();
while (it.hasNext()) {
T t = it.next();
it.remove(); // or remove until empty
}