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

时间:2016-03-17 18:56:28

标签: java hashmap hashcode

我实施了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
    }
}

2 个答案:

答案 0 :(得分:2)

它返回null,因为你已经改变了num1对象的数量,从而改变了它的hashcode。哈希映射使用hashcode()来存储和检索对象,因此当你更改它时,你会在错误的地方寻找一个对象,因为它存储在编号为2500的地方,但是你会在地点100上看它。那是因为你的hashcode返回数字。希望这会有所帮助。

答案 1 :(得分:2)

您创建了一个问题,因为您在将密钥放入Map后对其进行了修改,该密钥是根据编号从哈希码方法中获取的。

清理你的代码。更具体地说,使数字不可变,只通过公共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 + ")";
    }
}

我已在主要类中的代码中添加了注释:

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();;
    }