今天,当我试图发现一个错误时,我发现删除对象时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,这是保持树平衡的一部分。
如果只有一个子节点(或没有子节点),则意味着节点本身已被删除。如果该节点有两个子节点,则用其后继节点替换该节点。
如果始终从头开始删除,则该节点将被丢弃,您仍然可以使用该节点,但不会对其进行修改。如果从树的中间删除右节点,则会修改该条目以平衡树,因此在删除后使用该条目会看到修改后的条目。