自定义简易HashMap的remove方法无法更新映射条目问题求助
简易HashMap的remove方法失效原因分析
我尝试实现一个简易HashMap,用Node单向链表表示映射条目,通过Node[] nodes数组存储这些条目:
static final class Node { int key; int value; Node next; int hash; Node(int key, int value, Node next, int hash) { this.key = key; this.value = value; this.next = next; this.hash = hash; } }
下面是我写的remove方法,逻辑是先定位键在HashMap中的索引,再线性扫描对应链表节点并移除匹配的键:
public void remove(int key) { int hash = computeHash(key); Node node = nodes[hash]; if (node == null) { return; } Node prev = null; while (node.key != key && node.next != null) { prev = node; node = node.next; } if (node.key == key) { if (prev != null) { prev.next = node.next; } else if (prev == null) { node = node.next; } else { node = null; } size--; } }
调用这个方法后,即使执行了remove操作,调用get仍能获取对应值,比如测试代码:
MyHashMap map = new MyHashMap(); map.put(1, 1); map.put(2, 1); map.remove(1); System.out.println(map.get(1)); // 仍然返回1
失效原因拆解
局部变量引用修改不影响原数组
当要删除的是链表的头节点(也就是prev == null的情况),代码里的node = node.next;只是修改了局部变量node的指向,完全没有改动nodes[hash]这个数组元素的引用。原数组里的这个位置依然指向原来的头节点,所以get方法依然能找到它。冗余的else分支
代码里的else { node = null; }永远不会被执行,因为前面已经用if (prev != null)和else if (prev == null)覆盖了所有情况,这个分支完全多余。
修复方案
当prev == null时,需要直接修改数组的对应位置,把它指向头节点的下一个节点:
if (prev != null) { prev.next = node.next; } else { // 直接修改数组中的引用,替换头节点 nodes[hash] = node.next; }
这样就能真正把原数组里的头节点引用替换掉,删除操作才会生效。
内容的提问来源于stack exchange,提问作者Nam V. Do
相关产品推荐
相关产品推荐

