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方法,判断的依旧是两个对象的内存地址!