Java中的 equals() 和 hashCode() 契约

简介: 理解这两个方法非常的重要,尤其是将用户自定义的对象添加到Map中的时候。有时候就算是久经沙场的老程序员也弄不清楚该如何正确使用它们。这篇文章中,我将用一个例子让大家看看大家经常会犯的错误,然后解释equals()和hashCode()的正确的使用方法。

java.lang.Object类中有两个非常重要的方法:

publicbooleanequals(Object obj)

publicinthashCode()

理解这两个方法非常的重要,尤其是将用户自定义的对象添加到Map中的时候。有时候就算是久经沙场的老程序员也弄不清楚该如何正确使用它们。这篇文章中,我将用一个例子让大家看看大家经常会犯的错误,然后解释equals()和hashCode()的正确的使用方法。

image.png

1. 常见错误

常见的错误如下:

import java.util.HashMap;

publicclassApple {

   private String color;

   publicApple(String color) {

       this.color = color;

   }

   publicbooleanequals(Object obj) {

       if (!(obj instanceof Apple))

           returnfalse;  

       if (obj == this)

           returntrue;

       returnthis.color == ((Apple) obj).color;

   }

   publicstaticvoidmain(String[] args) {

       Applea1=newApple("green");

       Applea2=newApple("red");

       //hashMap stores apple type and its quantity

       HashMapm=newHashMap();

       m.put(a1, 10);

       m.put(a2, 20);

       System.out.println(m.get(newApple("green")));

   }

}

这个例子中,一个“绿苹果”的对象成功添加到hashMap中了,但是当我们要取出这个“绿苹果”的时候,却得不到这个对象,程序返回null。我们使用调试器却发现在hashMap中已经存储了这个对象。

image.png

2. hashCode()引起的问题

这个问题是因为”hashCode()”方法没有被重写。Java中equals()和hashCode()有一个契约:

  1. 如果两个对象相等的话,它们的hash code必须相等;
  2. 但如果两个对象的hash code相等的话,这两个对象不一定相等。

Map的结构能够快速找到一个对象,而不是进行较慢的线性查找。使用hash过的键来定位对象分两步。Map可以看作是数组的数组。第一个数组的索引就是对键采用hashCode()计算出来的值,再在这个位置上查找第二个数组,使用键的equals()方法来进行线性查找,直到找到要找的对象。

Object类中的hashCode()对于不同的对象返回不同的整数,所以上面的例子中,不同的对象(即使相同的类型)也返回不同的hash值。

Hash码就像是一个存储空间的序列,不同的东西放在不同的存储空间中。将不同的东西整理放在不同的空间中(而不是堆积在一个空间中)更高效。所以能够均匀的分散hash码是再好不过了。

上面错误的解决方法就是在类中增加hashCode方法。这里我仅仅使用颜色的长度来计算hash码。

publicinthashCode(){

   returnthis.color.length();

}



相关文章
|
8月前
|
存储 Java 开发者
Java 中的 equals 方法:看似简单,实则深藏玄机
本文深入探讨了Java中`equals`方法的设计与实现。默认情况下,`equals`仅比较对象引用是否相同。以`String`类为例,其重写了`equals`方法,通过引用判断、类型检查、长度对比及字符逐一比对,确保内容相等的逻辑。文章还强调了`equals`方法需遵循的五大原则(自反性、对称性等),以及与`hashCode`的关系,避免集合操作中的潜在问题。最后,对比了`instanceof`和`getClass()`在类型判断中的优劣,并总结了正确重写`equals`方法的重要性,帮助开发者提升代码质量。
626 1
|
存储 Java C++
java中“==”和equals,究竟比的是什么
java中“==”和equals,究竟比的是什么
180 4
|
存储 Java C++
java中“==”和equals,究竟比的是什么
java中“==”和equals,究竟比的是什么
144 3
java中“==”和equals,究竟比的是什么
|
存储 Java
【Java基础面试二十三】、==和equals()有什么区别?
这篇文章区分了Java中的`==`运算符和`equals()`方法:`==`用于基本数据类型时比较值是否相等,用于引用类型时比较内存地址是否相同;而`equals()`默认实现按内存地址比较,但通常被重写以根据对象内容比较是否相等。
【Java基础面试二十三】、==和equals()有什么区别?
【Java基础面试二十一】、说一说hashCode()和equals()的关系
这篇文章讨论了Java中`hashCode()`和`equals()`方法之间的关系,强调如果两个对象相等,它们必须有相同的哈希码,但有相同哈希码的对象未必相等,并解释了这一关系在HashSet集合中判断元素是否重复的应用场景。
【Java基础面试二十一】、说一说hashCode()和equals()的关系
【Java基础面试二十二】、为什么要重写hashCode()和equals()?
这篇文章解释了为什么需要重写`hashCode()`和`equals()`方法:因为Object类的`equals()`默认使用`==`比较,这在业务中通常是不够的,我们需要根据对象内容来比较相等性;同时,为了保持`hashCode()`与`equals()`的联动关系,一旦重写了`equals()`,通常也需要重写`hashCode()`。
【Java基础面试二十二】、为什么要重写hashCode()和equals()?
|
存储 Java 索引
|
存储 Java 索引
java 中为什么重写 equals 后需要重写 hashCode
java 中为什么重写 equals 后需要重写 hashCode
271 8
JAVA中比较对象是否相等的方式是什么?为什么重写equals就一定要重写hashcode?百天百题(3/100)
JAVA中比较对象是否相等的方式是什么?为什么重写equals就一定要重写hashcode?