KeySetView按值循环

时间:2018-04-21 10:24:50

标签: java loops concurrenthashmap

我正在通过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

1 个答案:

答案 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
}