HashMap存自定义对象为什么要重写 hashcode 和 equals 方法?

mac2024-08-07  62

HashMap的k放过自定义对象么? 当我们把自定义对象存入HashMap中时,如果不重写hashcode和equals这两个方法,会得不到预期的结果。

class Key{     private Integer id;

    public Integer getId() {         return id;     }

    public Key(Integer id) {         this.id = id;     } } public class WithoutHashCode{     public static void main(String[] args){        //定义两个对象,并声明他俩的id全是1         Key k1 = new Key(1);         Key k2 = new Key(1);         HashMap<Key,String> map = new HashMap<Key,String>();         map.put(k1, "Key with id is 1");         System.out.println(map.get(k2));     } } 在这里把k1对象作为键put进HashMap,再用k2来get出来并打印。如果没有重写hashcode和equals方法,最终只能得到一个null。 原因很简单,由于我们没有重写hashcode方法,所以在往HashMap中放入k1时依旧调用的是Object类的hashcode方法,返回的是k1对象的内存地址。如果是用map.get(k1)来查找,就能很快得到value值。 但遗憾的是,我们偏偏是用的k2来get。Object的hashcode方法返回的是k2的内存地址,肯定和k1的不相同,换句话说就是他俩的hash值不同,所以不能用k2的hash值拿到k1的value。

重写hashCode和equals方法 class Key{     private Integer id;

    public Integer getId() {         return id;     }

    public Key(Integer id) {         this.id = id;     }     @Override     public boolean equals(Object o) {         if (o==null || !(o instanceof Key)){             return false;         }else {             return this.getId().equals(((Key)o).getId());         }     }

    @Override     public int hashCode() {         return id.hashCode();     } } 只重写了hashCode方法后,这里的hashCode方法return的是id的hashCode值。因为我们之前将两个对象的id都设为1,所以他俩的hash值是一样的。 接下来我们再去map.get(k2),会不会拿到value呢?结果还是null。目瞪狗呆有木有?为啥嘞?不是都已经使他俩的hashCode相同了嘛?因为我们只是重写了hashCode方法,并没有重写equals方法啊。不要忘了,HashMap是用链地址法来处理碰撞冲突的。也就是说,某一条链表上的所有的元素的hashCode返回的hash值全是一样的。只重写hashCode方法只能证明k1和k2的hash值相同,当时并不代表他俩就是相等。没有重写equals方法,又是会调用Object类中的equals方法,判断的依旧是两个对象的内存地址!  

最新回复(0)