聚合国内IT技术精华文章,分享IT技术精华,帮助IT从业人士成长

简易Java(15):Java中equals()与hashCode()之间的联系

2014-11-15 15:50 浏览: 1653541 次 我要评论(0 条) 字号:

Hash函数

Java的最基本的父类java.lang.Object中有两个非常重要的方法定义:


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

实践证明,正确理解这两个方法非常重要,尤其是向Map中添加用户自定义的对象时。即便如此,甚至有些高级开发人员有时很很难说清楚它们到底应该怎么用。在这篇文章里,我将先展示几个常见的错误例子,然后再解释这两个方法如何才能正确地配合。

1、一个常见错误

在下面的代码中,展示了一个常见的错误。


package com.diguage.books.simplejava.ar15;

import java.util.HashMap;
import java.util.Map;

/**
* equals()方法的错误示例
* <p/>
* Coder:D瓜哥,http://www.diguage.com/
* <p/>
* Date: 2014-11-09 21:40
*/
public class Apple {
private String color;

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

@Override
public boolean equals(Object obj) {
if (!(obj instanceof Apple)) {
return false;
}

if (this == obj) {
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
Map<Apple, Integer> m = new HashMap<Apple, Integer>();
m.put(a1, 10);
m.put(a2, 20);

System.out.println(m.get(new Apple("green")));
}
}

在这里例子里,一个绿色苹果的对象被成功存储到HashMap中。但是,从这个Map中取出这个苹果时,这个苹果对象却找不到了。上面的程序输出为null。但是,在通过调试器,我们非常确定这个对象就存储在HashMap中。如下图:

Eclpse调试页面

2、hashCode()造成的问题

这个问题是由于没有覆盖hashCode()equals()hashCode()之间的契约是这样的:1)如果两个对象是相等的,那么它们必须有相同的哈希值(Hash Code);2)如果两个对象有相同的哈希值,那么它们未必一定相等。

Map的一种隐含意义就是比线性搜索能更快地找到对象。使用经过哈希计算过的键值去定位对象需要两步处理。在Map内部,对象被存在数组中的数组中。第一层数组的下标就是键的hashCode()返回值。搜索第二层数组是使用线性搜索,通过使用equals()来判断对象是否被找到。

D瓜哥注

这里对java.util.HashMap内部实现的描述并不是十分准确。根据源代码显示,第一层确实是数组,如果有Key的哈希值一样,即哈希冲突,则将其存为一个链表。感兴趣的小伙伴可以自己查看一下HashCode的源代码。

hashCode()Object类中的默认实现是,针对不同的对象,返回不同的整数值。因此,在上述例子中,不同的对象(即使是同一类型)有不同的哈希值。

哈希值就像一系列用于存储的仓库,不同的物品存放在不同的仓库里。相比将物品存放到同一个仓库,存放到不同地方会更加高效。因此,使用平均分散的哈希值是一个非常好的实践。(这不是本文重点,不再展开讲。)

解决办法就是在类中覆盖hashCode()方法。针对这个示例,我使用color字符串的长度即可。代码如下:

D瓜哥注

这不是好的实现方式,但是仅仅是针对本例已经足矣。


/**
* 本例子中hashCode() 方法的的正确使用
* <p/>
* Coder:D瓜哥,http://www.diguage.com/
* <p/>
* Date: 2014-11-09 21:40
*/
public int hashCode() {
return this.color.length();
}

《Simple Java》是一本讲解Java面试题的书。讲解也有不少独特之处,为了面试,《简易Java》走起!



网友评论已有0条评论, 我也要评论

发表评论

*

* (保密)

Ctrl+Enter 快捷回复