前言
关于equals以及hashCode相关知识网上已经非常非常多了,最近在看到这篇博文的时候总感觉还是少了些,故自己写了一些测试代码,然后总结一下到底这两个有什么相同点以及不同点。
equals
equals方法是用来比较两个对象是否相等,一般来说要想编写一个合格的equals方法需要以下几个步骤
1、判断对象内存地址是否相等
2、判断对象class类型是否相等
3、判断字段
class TestPerson { public String name; public int age; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TestPerson that = (TestPerson) o; return age == that.age && Objects.equals(name, that.name); } }
equals方法在List、Queue的数据结构中经常用到,比如List#contains、List#indexOf,判断元素是否相等。
hashCode
hashCode方法是用来生成当前对象的哈希码,一般来说,同一个对象的哈希码是一样的,但是相同的哈希码不一定是同一个对象(哈希冲突),既然我们通过equals可以判断是否为统一同一对象,那么为什么还需要hashCode。
对于Set、Map等数据结构来说,判断元素是否重复使用equals的话,那么就每一次都需要遍历所有元素,那么就失去了其原来的目的(空间换时间),所以这时候对于Set、Map则会使用对象的hashCode来计算出对象的存储位置,然后使用equals去判断对象是否相同,如果不同,那么就发生了哈希冲突,至于如何解决哈希冲突,则不是我们的问题了。
下面的例子是使用Objects为我们提供的Hash计算方法。
class TestPerson { public String name; public int age; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TestPerson that = (TestPerson) o; return age == that.age && Objects.equals(name, that.name); } @Override public int hashCode() { return Objects.hash(name, age); } }
总结
equals方法是用来判断两个对象是否相等,默认的实现为直接判断对象内存地址是否相同,我们可以覆写然后判断指定的字段
hashCode方法只是用来获取对象的哈希码,当哈希码不同那么Set、Map则会将其当做两个不一样的对象,所以才必须:同一个对象的hashCode的返回值必须一样。当我们没有覆写hashCode方法,那么会导致Set中可以存在equals相同的元素(因为通过HashCode算出的位置不同,然后就是两个不同的对象了),Map中Key可以为equals相同的元素(原理一样)。