今天,当我试图发现一个错误时,我发现删除对象时TreeMap迭代器的行为有些奇怪。实际上,在一个简单的示例中,我测试了不同的用途:

    TreeMap<String, String> map = new TreeMap<String, String>();
    map.put("1", "1");
    map.put("2", "2");
    map.put("3", "3");
    map.put("4", "4");
    map.put("5", "5");

    Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();

     while (iterator.hasNext()) {
        Map.Entry<String, String> entry = iterator.next();
        System.out.println("Before "+entry.getKey());
        iterator.remove();
        System.out.println("After " +entry.getKey());
    }

结果是:
Before 1
After 1
Before 2
After 2
Before 3
After 3
Before 4
After 4
Before 5
After 5

但是,如果我将其更改为:
    TreeMap<String, String> map = new TreeMap<String, String>();
    map.put("1", "1");
    map.put("2", "2");
    map.put("3", "3");
    map.put("4", "4");
    map.put("5", "5");

    Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();

            String key = "4";

    while (iterator.hasNext()) {
        Map.Entry<String, String> entry = iterator.next();
        if(entry.getKey().equals(key)){
            iterator.remove();
            System.out.println(entry.getKey());
        }
    }

然后,对于key = 4,结果为5,而对于key = 5,结果为5,这是因为链接在移除后发生了更改。但是为什么行为不同。准时吗即使是答案,他们也不应该统一吗?

最佳答案

为了回答为什么会发生此问题,该注释给出了提示

// If strictly internal, copy successor's element to p and then make p
// point to successor.

AFAIK,这是保持树平衡的一部分。

如果只有一个子节点(或没有子节点),则意味着节点本身已被删除。如果该节点有两个子节点,则用其后继节点替换该节点。

如果始终从头开始删除,则该节点将被丢弃,您仍然可以使用该节点,但不会对其进行修改。如果从树的中间删除右节点,则会修改该条目以平衡树,因此在删除后使用该条目会看到修改后的条目。

09-11 17:35