本文共 3189 字,大约阅读时间需要 10 分钟。
首先我们需要弄清楚equals()方法和hashCode()方法是什么?
**equals()**方法用于判断两个对象是否想同,不能用于比较基础类型的数据。equals()方法是存在于Object类中的,他是所有类直接或间接的父类,所以,所有的类都有equals()方法。
**hashCdoe()**方法是用于获取哈希码的,哈希码是一个int类型的整数,用于确定对象在哈希表中的索引位置。哈希码在Java中的作用是,在具有哈希结构的容器中,如HashTable、HashMap、HashSet。在向这些容量里面添加对象的时候,会先使用hashCode()方法计算该对象的哈希码,如果哈希码相同,会使用equals()方法来判断两个对象是否真的相同,如果相同就不会让其加入该位置;如果不同则让其加入。这样可以减少equals()的执行次数从而提高执行效率,因为equals()方法的开销是比hashCode()方法的开销大的。hashCode()方法和equals()方法一样是存在于Object类中的
那么为什么重写了quals()方法时必须要重写hashCode()方法呢?
我们知道如果两个对象相等,他们的hashCode是一定相等的,且他们调用equals()方法比较返回的结果一定是true。但是如果两个对象的hashCode相同,他们不一定是相等的(可能产生了哈希碰撞),所以equals 方法被覆盖过,则 hashCode 方法也必须被覆盖。
下面我们来举例说明一下,这是我自定义的一个Person类,里面有id(身份证)、phoneNum(电话号码)两个属性。
public class Person { private int id; private int phoneNum; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getPhoneNum() { return phoneNum; } public void setPhoneNum(int phoneNum) { this.phoneNum = phoneNum; }}
我们假设只要id(身份证)相同的两个Person他们就是同一个人,如果我们不重写equals()方法,这两个对象不会是同一个人
public static void main(String[] args) { Person person1 = new Person(666666, 1888888888); Person person2 = new Person(666666, 1666666666); System.out.println(person1.equals(person2)); // 结果为:false }
如果我们要让具有相同id的Person为同一个人的话,我们需要重写eauals()方法,注意,此时我们没有重写hashCode()方法
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return id == person.id; }
重写equals()方法之后,我们再次运行结果为true,说明这两个Person是同一个人了
public static void main(String[] args) { Person person1 = new Person(666666, 1888888888); Person person2 = new Person(666666, 1666666666); System.out.println(person1.equals(person2)); // 结果为:true }
此时我们把这个两个person放入具有哈希结构的容器中,我们将这两个Person放入HasSet中
public static void main(String[] args) { Person person1 = new Person(666666, 1888888888); Person person2 = new Person(666666, 1666666666); Setset = new HashSet<>(); set.add(person1); set.add(person2); System.out.println(person1.equals(person2)); // 结果为:true System.out.println(set.size()); // 结果为:2 }
因为我们规定了具有相同id(身份证)的Person为同一个人,所以person1.equals(person2)为“true”,这样的话set里面的大小应该为1,但结果是为2,说明在HashSet看来这两个Person还不是同一个人。这是因为HashSet在添加对象的时候会先调用hashCode()方法计算哈希码,来确定该对象在哈希表中的索引位置。我们没有重写hashCode()方法,当计算person1和person2的哈希码的时候,是不同的,HashSet就会认为这两个对象时不同的,但此时equals()方法返回的结果是true,这就造成了结果的不一致。
所以,我们需要重写hashCode()方法来保证结果的一致性,我们重写hashCode()方法
@Override public int hashCode() { return Objects.hash(id); }
再次运行程序,可以发现此时set的大小为1了,与我们预期的结果是一致的,这就是为什么重写equals()方法必须要重写hashCode()方法。
public static void main(String[] args) { Person person1 = new Person(666666, 1888888888); Person person2 = new Person(666666, 1666666666); Setset = new HashSet<>(); set.add(person1); set.add(person2); System.out.println(person1.equals(person2)); // 结果为:true System.out.println(set.size()); // 结果为:1 }
转载地址:http://ryfef.baihongyu.com/