博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么重写equals()方法时必须要重写hashCode()方法
阅读量:2107 次
发布时间:2019-04-29

本文共 3189 字,大约阅读时间需要 10 分钟。

为什么重写equals()方法时必须要重写hashCode()方法

首先我们需要弄清楚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); Set
set = 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); Set
set = 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/

你可能感兴趣的文章
C#基础概念二十五问
查看>>
C#在Excel中将连续多列相同数据项合并
查看>>
C#如何把html中的相对路径变成绝对路径
查看>>
用C#编写发手机中文短信息Windows服务
查看>>
C#的四个基本技巧
查看>>
编程实例 使用C#的BitmapData
查看>>
区分Oracle和SQL Server常用函数调用方法
查看>>
详解Visual C#数据库基本编程
查看>>
第一个C#应用程序
查看>>
第一章C#简介
查看>>
NGWS runtime 技术基础
查看>>
Linux find 文件查询 用法示例
查看>>
Linux 查看文件大小
查看>>
mysql 命令
查看>>
MySQL执行外部sql脚本文件的命令
查看>>
解决MySql Error Code: 2006
查看>>
查看mysql数据库和表所占用空间
查看>>
Guava Collections使用介绍
查看>>
Ordering犀利的比较器
查看>>
spring+Mybatis+Ehcache整合
查看>>