You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:58:25