为何HashMap中修改对象属性后,重写equals/hashCode会返回null?
为什么修改HashMap中Key对象的属性后,get()返回结果不同?
先看你提供的测试代码:
// Trying to check how hashmap works public class hashmapcheck { public static void main(String args[]) { Person abhishek = new Person("abhishek"); Map<Person,String> mapCheck = new HashMap<Person,String>(); mapCheck.put(abhishek,"ancd"); abhishek.setName("defg"); System.out.println(mapCheck.get(abhishek)); //line which i try to understand } } public class Person { public String getName() { return name; } public void setName(String name) { this.name = name; } public Person(String name) { this.name = name; } String name; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return name != null ? name.equals(person.name) : person.name == null; } @Override public int hashCode() { return name != null ? name.hashCode() : 0; } }
你观察到的现象:
当未重写Person类的equals和hashCode方法时,执行代码输出"ancd";重写这两个方法后,输出"null"。原以为HashMap存储的是对象引用,想了解此现象的原因。
这个问题刚好能帮你搞懂HashMap的核心查找逻辑——它不是直接通过对象引用定位元素,而是靠hashCode()找桶,再靠equals()匹配具体的Entry。咱们分两种情况拆解:
1. 未重写equals和hashCode的场景
Java中所有类默认继承自Object,Object的hashCode()返回对象的内存地址哈希值,equals()则直接比较两个对象的引用是否相同(是不是同一个对象)。
- 执行
put(abhishek,"ancd")时,HashMap用abhishek当时的hashCode(基于内存地址)找到对应的桶,把Entry存进去。 - 修改
abhishek的name属性后,这个对象的内存地址并没有变,所以它的默认hashCode还是原来的数值。 - 调用
get(abhishek)时,HashMap用同样的hashCode找到原来的桶,再用equals比较——因为是同一个对象引用,equals返回true,所以顺利拿到"ancd"。
2. 重写了equals和hashCode的场景
你重写后,hashCode()和equals()都绑定了name属性:
put的时候,abhishek的name是"abhishek",HashMap用这个字符串的哈希值找到对应的桶,把Entry存进去。- 调用
setName("defg")后,abhishek的hashCode变成了"defg"的哈希值,和存储时的哈希值完全不同。 - 现在调用
get(abhishek),HashMap会用新的hashCode去找桶,这个桶和当初存Entry的桶根本不是同一个,自然找不到对应的元素,返回null。
哪怕极端情况下新的hashCode刚好落到原来的桶里,equals比较也会失败——现在的name是"defg",而存储时Key的name是"abhishek",equals返回false,还是拿不到值。
总结一下:HashMap确实存储了对象的引用,但查找元素的逻辑依赖于hashCode()和equals()的实现。如果用可变对象作为Key,并且hashCode()/equals()依赖可变属性,修改属性后就会破坏HashMap的查找逻辑,导致找不到原来的Entry。这也是为什么Java推荐用不可变对象(比如String、Integer)作为HashMap的Key。
内容的提问来源于stack exchange,提问作者abhishek vashistha
相关产品推荐
相关产品推荐

