你的位置:首页 > Java教程

[Java教程]【Simple Java】equals()和hashCode()之间的关系


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

public boolean equals(Object obj)public int hashCode()

对这两个方法的理解非常重要,特别是当用户自己定义对象,并将其存入到Map中的时候;

然而,即便是高级开发人员,有时候也搞不清楚如何正确的使用它们;

在这篇文章,我首先会展示一种常见的错误示例,然后解释如何正确的使用这两个方法;

常犯的错误

如下代码是常见的错误使用示例:

package simplejava;import java.util.HashMap;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 class Q9 {  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")));  }}

在这个例子中,一个绿色苹果对象成功存入到hashMap中,但是当我们要取出来的时候,得到的却是null;然而通过调试程序,我们确实看到了hashmap中的绿苹果对象;

错误原因-hashcode()方法导致

之所以出现这个错误是因为没有重写hashCode()方法导致的。

hashCode()和equals()的关系是这样的:

如果两个对象相等(equal),它们的hashcode一定相同;

如果两个对象有相同的hashcode,它们不一定相等(equal);

之所以这样设计是为了在Map中更快的查找到对象(相对于线性搜索);

一般Map都设计成数组+链表的结构,使用hashcode去查找对象需要两个步骤,首先使用hashcode定位数组下标索引,然后遍历该数组元素对应的链表,找到equals的元素;

Object默认的hashcode实现对于不同的对象会返回不同的值,因此,在上面那个例子中,不同的对象(即使同一个类型)有着不同的hashcode;

值的散列就像在车库储存货物,不同的货物能被存放到不同的车库。比较有效查找货物办法是将不同的货物存到不同的车库中,而不是同一个车库;

所以将hash值尽可能的分散是一个比较好的策略;

关于这个例子,解决办法是添加hashcode方法,这里我将使用颜色的长度作为示范,如下代码:

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

 

译文链接:http://www.programcreek.com/2011/07/java-equals-and-hashcode-contract/