JAVA中==,equals(),hashCode()

本文深入探讨了Java中对象比较的三种方式:引用等价性(==)、对象等价性(equals())以及哈希码(hashCode())。详细阐述了它们的功能、特点及相互关系。特别是强调了当重写equals()方法时,通常需要重写hashCode()以确保哈希表操作的正确性。此外,还解释了hashCode()在哈希表存储中的作用,以及其与equals()的协定。
摘要由CSDN通过智能技术生成

目录

1 前言

2 对象比较的方法

   2.1 ==

   2.2 equals()

   2.3 hashCode()

      2.3.1 Hash Tables

      2.3.2 hashCode()方法

3 equals与hashCode关系探究

   3.1 equals与hashCode

   3.2 重写equals方法需要重写hashCode吗?


 

1 前言

java中==,equals(),hashcode()三种方法都与对象比较有关,本文将分别探究三种方法各自的功能与特点,同时重点讨论equals()与hashcode()两种方法的联系与区别。

 

2 对象比较的方法

2.1 ==

java有两种等价性比较,分别是引用等价性和对象等价性。==在java中进行的比较是引用等价性,即比较的是两个对象在内存中的引用地址是否相同。

对于基本数据类型,==比较的是它们的值是否相等;

对于对象类型,==比较的是两个对象在内存中的引用地址是否相等(即是否指向内存里的同一段空间)。

 

2.2 equals()

与==不同,equals()在java中进行的比较是对象等价性,即对于对象类型,判断它们的值是否相等。但需要注意的一点是,在自定义ADT时,需要重写Object的equals() !

这是因为equals()方法是被Object定义的,且它的默认执行是:

public class Object {
    ...
    public boolean equals(Object that){
        return this == that;
    }
}

因此在Object中实现的默认equals()是在判断引用等价性,所以我们需要重写equals()方法(对于封装类如String、Integer等,它们的equals方法是已经被重写了的)。

同时,当重写equals()方法时,必须要遵照它的通用约定:

1. equals必须定义一个等价关系(自反,传递,对称)

2. 除非对象被修改了,否则调用多次equals应是同样的结果

3. 对于一个非空的对象x,x.equals(null)应该返回false

4. “相等”的对象,其hashCode()的结果必须一致

 

2.3 hashCode()

2.3.1 Hash Tables

首先我们要先知道Java中的集合。总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。

而我们保证元素不重复的方法就是Object.equals方法。但是如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。这显然会大大降低效率。于是,Java采用了 Hash Tables 的原理。  

我们介绍一下 Hash Tables 的概念:一个hash table就是一种映射keys到values的抽象数据型。对于keys和values,我们需要计算keys的hashcode,并将它转换为一个数组范围内的索引,最后values就插入在那个索引处。

因此,当集合需要添加新的元素时,通过hashcode方法,我们可以返回一个地址索引值:

1. 当那个索引处没有元素,则直接存入;

2. 当那个索引处有元素,则调用equals方法,若两个元素相等,则无需再存;否则就再寻找其他地址。

通过这样,我们可大大提高性能。

 

2.3.2 hashCode()方法

hashCode()方法在官方文档的定义如下:

public native int hashCode();

即返回一个int型数据,在Object类中的默认实现是“将该对象的内部地址转换成一个整数返回”。

 

3 equals与hashCode关系探究

3.1 equals与hashCode

首先查阅官方文档中 hashCode 的常规协定:

1. 在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。   
2. 如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。   
3. 以下情况不 是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。   
4. 实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)   

由此,我们可以总结:

1. equals判定等价的对象的hashCode必须相同;

2. equals判定不相等的对象也可以映射为相同的hashCode,但性能会变差。

 

3.2 重写equals方法需要重写hashCode吗?

根据官方文档:

当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

同时,Object的默认hashCode()的执行与默认的equals()的执行是一致的。

public class Object{
    ...
    public boolean equals(Object that) { return this == that; }
    public int hashCode() { return /*the memory address of this */ ; }
}

因此,对于类的对象存储在HashTable,HashSet,HashMap等散列存储结构的情况,那么重写equals后必须也重写hashCode,否则会导致存储数据的不唯一性(存储了两个equals相等的数据)。

最后,我们可以总结:当你重写了equals方法后,最好也重写hashCode方法,除非你能保证你的ADT不会被放在Hash类型的集合类中。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值