为什么 HashMap get() 方法 returns 在修改插入的对象后为 null?

Why does HashMap get() method returns null after modifying an inserted object?

我实现了 overriding equals and hashCode correctly。在下面的代码中,当我打印出 map 和 num1 时,我可以在控制台中看到它们都有更新的 hashCode()。但是当我试图将它从地图中取出时,它说它是空的。谁能帮忙解释一下为什么 .get() 方法找不到它?

class Phone {

    int number;

    Phone(int number) {this.number = number;}

    public int hashCode() {
        return number;
    }

    public boolean equals(Object o) {
        if (o != null && o instanceof Phone)
            return (number == ((Phone)o).number);
        else
            return false;
    }

    public static void main(String args[]) {
        Map<Phone, String> map = new HashMap<>();
        Phone num1 = new Phone(2500);
        map.put(num1, "John");
        num1.number = 100;

        System.out.println(map);
        System.out.println(num1);
        System.out.println(map.get(num1)); // why does it print null
    }
}

它returnsnull,因为你改变了num1对象的个数,从而改变了它的hashcode。哈希映射使用 hashcode() 来存储和检索对象,因此当您更改它时,您会在错误的位置查找对象,因为它存储在编号为 2500 的位置,但随后您会在位置 100 查找它。那是因为您的hashcode returns 数字。希望这有帮助。

您创建了一个问题,因为您在将密钥放入 Map 后修改了密钥,该 Map 根据数字从您的 hashcode 方法中进行了哈希处理。

稍微清理一下您的代码。更具体地说,使数字不可变,并且只能通过 public getter 方法访问数字。您不应允许 Map 中的键可变。

public class MyNumber {
    private int number;

    public MyNumber(int number) {
        this.number = number;
    }

    public int getNumber(){
        return number;
    }

    @Override
    public int hashCode() {
        return number;
    }

    @Override
    public boolean equals(Object o) {
        if (o != null && o instanceof MyNumber) {
            return (number == ((MyNumber) o).number);
        }
        else {
            return false;
        }
    }

    @Override
    public String toString(){
        return this.getClass().getName() + "(" + number + ")";
    }
}

我已经在您的主要代码中添加了注释 class:

import java.util.HashMap;
import java.util.Map;

public class OverrideHashCode {

    public void mutableObjectKeys() {
        Map<MyNumber, String> map = new HashMap<>();
        MyNumber num1 = new MyNumber(2500);
        map.put(num1, "Shreya");

        System.out.println(map);
        System.out.println(num1);

       //This line was your issue. You placed the MyNyumber in the map
        //The hashcode pulls the number value from MyNumber to hash the entry (2500 )
        //Then you change the value of number
        //num1.getNumber() = 100;
        System.out.println(map);
        System.out.println(num1);

        //This was hashed at 2500, but you changed the MyNumber to 100 - no match
        System.out.println(map.get(num1)); // prints null - not anymore

        //Let's put a second object in the Map
        map.put(new MyNumber(500), "GroovyIsBetter!");

        //When you work with Maps, you are commonly trying to get values out of the map based on the key.
        //In this example, our key's are MyNumber(s)
        //We have made MyNumber.number immutable (which is good).
        //Because you implemented your own hashcode and equals, you can even pull the value out of the map
       //with a new MyNumber object that has the same number value as the original key you placed in the map
        System.out.println("\n" + map.get(new MyNumber(2500)));
        System.out.println(map.get(new MyNumber(500)));

        //Now we can remove one of the keys and recheck
        //Should come up null
        map.remove(new MyNumber(500));
        System.out.println(map.get(new MyNumber(500)));
    }

    public static void main(String... args){
        new OverrideHashCode().mutableObjectKeys();;
    }