为什么在JavaTreeMap中调用iterator.remove()时相同的Map.Entry会发生变化?

当我使用Iterator迭代 some 时TreeMap,我发现相同Map.Entry的内容会发生变化。例如:

import java.util.Map.Entry;
import java.util.TreeMap;

public class Solution {
    public static void main(String[] args) {
        TreeMap<Integer, Integer> map = new TreeMap<>();
        map.put(1,1);
        map.put(2,2);
        map.put(3,3);
        System.out.println("map: " + map);
        Map<Integer, Integer> fromMap = map.tailMap(2);
        System.out.println("fromMap: " + fromMap);
        Iterator<Entry<Integer, Integer>> iter = fromMap.entrySet().iterator();
        Entry<Integer, Integer> entry = iter.next();
        System.out.println(entry); // line 1  
        iter.remove();
        System.out.println(entry); // line 2. Why does entry content change?
    }
}

结果:

map: {1=1, 2=2, 3=3}
fromMap: {2=2, 3=3}
2=2
3=3

entry在第1行和上述代码中的线2具有相同的参考,但是当我所说的内容改变iter.remove()

回答

从 Javadoc Map.Entry 中明确

如果在迭代器返回条目后修改了后备映射,则映射条目的行为是未定义的,除非通过对映射条目的 setValue 操作

从Map.Entry.getValue()

返回与此条目对应的值。如果映射已从支持映射中删除(通过迭代器的删除操作),则此调用的结果未定义

这意味着 Java 不保证如果您调用entryafterremove方法并且它未定义会发生什么 。

  • In other words, the implementation does not break the contract. But the behavior is really dangerous. I'd have hoped to get immutable entries!
  • For reference, here's a comment of [Joshua Bloch on Twitter](https://twitter.com/joshbloch/status/1408718009833713669?s=21) on the reason why this choice had been made back in the days : `It seemed like a good idea at the time. Computers were 1000 times slower and had 1000 times less memory (roughly speaking).`

以上是为什么在JavaTreeMap中调用iterator.remove()时相同的Map.Entry会发生变化?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>