Java中equals()和hashCode()的区别与联系

时间:2022-04-05 13:20:27
Java中equals()和hashCode()的区别与联系
Java的超类java.lang.Object定义了两个非常重要的方法:
public boolean equals(Object obj)
public int hashCode()
理解这两方法之间的区别联系是非常重要的,特别是当用户自定义的对象被添加到Map中。然而,即使高级开发人员有时无法弄清楚他们应该如何正确使用。在这篇文章中,我会先给大家看一个常见的错误的例子,然后解释如何的equals()和hashCode()之间的区别联系。
1.一个常见的​​错误
请看下面的例子:

import java.util.HashMap;

public class Apple {
private String color;

public Apple(String color) {
this.color = color;
}

public boolean equals(Object obj) {
if (!(obj instanceof Apple))
return false;
if (obj == this)
return true;
return this.color.equals(((Apple) obj).color);
}

public static void main(String[] args) {
Apple a1 = new Apple("green");
Apple a2 = new Apple("red");

//hashMap stores apple type and its quantity
HashMap<Apple, Integer> m = new HashMap<Apple, Integer>();
m.put(a1, 10);
m.put(a2, 20);
System.out.println(m.get(new Apple("green")));
}
}


在这个例子中,一个color属性为“green”的Apple对象被成功地存储在一个HashMap中,但是当Map被要求获取该对象时,结果发现Apple对象没有找到。上面的程序在控制台打印为null。但是,我们可以肯定的是,通过在调试器可以查看到对象确实是存储在HashMap中:
Java中equals()和hashCode()的区别与联系
2.hashCode()造成的问题
这个问题是由未重写的方法hashCode()引起的。equals()和hasCode()之间的制约关系是:
1.如果两个对象是相等的,那么它们必须有相同的哈希码。
2.如果两个对象具有相同的哈希码,他们可能相等,可能不相等。
一个Map背后的想法是能够比线性搜索更快地定位到对象。使用散列键定位对象是一个两步的过程。Map内部存储对象是以数组的数组来存储。1.第一个数组的索引是hashCode()值的key。2.定位第二个数组(使用线性搜索找到的)是通过使用equal()来决定对象是否被找到?

hashCode()的默认实现是Object类为不同的对象返回不同的整数。因此,在上面的例子中,不同的对象(即使是相同类型的)具有不同的哈希码。

哈希码的存储就像车库中的序列一样,不同的车(对象)可以被存储在不同的车库中。如果你将不同的车(对象)放在不同的车库中而不是相同的车库中,那么会更有效。所以平均分配的hashCode值是一个很好的做法。(虽然不是这里的要点)

下面的例子是为一个类添加hashCode()方法的简单的解决方案,在这里,我只是用color字符串的长度作示范。

public int hashCode(){
return this.color.length();
}

相关文章:

  1. Java hashCode() and equals() Contract for the contains(Object o) Method of Set
  2. HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap
  3. Yet Another “Java Passes By Reference or By Value”?
  4. What does a Java array look like in memory?
原文:

Java equals() and hashCode() Contract