java的object重写equals时为什么有必要重写hashcode

转载的:自己觉得很有用,存起来http://blog.sina.com.cn/s/blog_6e5e2eb701012qxv.html

浅谈为何要重写 hashcode()与equals()

    首先,这两个方法都来自于Object对象,根据API文档查看下原意。(1)public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true;注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。(2)public int hashCode() 返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。

    我们知道,如果不重写equals,那么比较的将是对象的引用是否指向同一块内存地址,重写之后目的是为了比较两个对象的value值是否相等。特别指出,此时,利用equals比较八大包装对象(如int,float等)和String类(因为该类已重写了equals和hashcode方法)对象时,默认比较的是值,在比较其它对象都是比较的引用地址。那产生了一个问题,为什么jdk中希望我们在重写equals时,非常有必要重写hashcode呢?

    我的理解是hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都是根据存储对象的hashcode值来进行判断是否相同的。这样如果我们对一个对象重写了euqals,意思是只要对象的成员变量值都相等那么euqals就等于true,但不重写hashcode,那么我们再new一个新的对象,当原对象.equals(新对象)等于true时,两者的hashcode却是不一样的,由此将产生了理解的不一致,如在存储散列集合时(如Set类),将会存储了两个值一样的对象,导致混淆,因此,就也需要重写hashcode。为了保证这种一致性,必须满足以下两个条件

    (1)当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true
    (2)当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false

     下面,通过一个简单的例子来验证一下。

import java.util.*;

class BeanA {
private int i;

public BeanA(int i) {
   this.i = i;
}

public String toString() {
   return "   " + i;
}

public boolean equals(Object o) {
   BeanA a = (BeanA) o;
   return (a.i == i) ? true : false;
}

public int hashCode() {
   return i;
}

}

public class HashCodeTest {

public static void main(String[] args) {
   HashSet<BeanA> set = new HashSet<BeanA>();
   for (int i = 0; i <= 3; i++){
    set.add(new BeanA(i));
   }
   System.out.println(set);
   set.add(new BeanA(1));
   System.out.println(set.toString());
   System.out.println(set.contains(new BeanA(0)));
   System.out.println(set.add(new BeanA(1)));
   System.out.println(set.add(new BeanA(4)));
   System.out.println(set);

}

}

我们在类BeanA中重写了equals和hashcode方法,这样在存储到HashSet数据集中,将保证不会出现重复的数据;如果把这两个方法去掉后,那些重复的数据仍会存入HashSet中,这就与HashSet强调的元素唯一性相违背,大家可以把这两个方法注释掉再运行一下。

再结合着别人的回答看就明白了很多:http://zhidao.baidu.com/question/287474398.html&__bd_tkn__=6ea745613d6c9d624f1abf638da423b9984f95e78078338d51fed8133ea5c69d362ad36bb4bcda3b39bb3949f6bbe47087ac3af56e60b1f4e7eb60157a54fa369a63aaf1560f03de0125276ad431bc063c759d727922#finish-value

java中重写Object类的equals方法为什么要重写hashcode方法?不重写可以吗?

要求是需要重写的,实践上是可以不重写的,反正编译器不会报错,一般情况下也不回出问题,只要你不用类似于Hashtable存放这些对象。之所以要求hashcode和equals一致,主要考虑的还是Hashtable问题。举个例子:假如你了重写A类的equals方法,而且有两个对象a1和a2按照这个方法比较是相等的。现在你要把这两对象分别作为另外两个对象v1和v2的key(类似于名字)放入Hashtable h中,也就是要:h.put(a1,v1); h.put(a2,b2);这样,由于a1和a2是相等的,按理说put(a2,b2);时应该把a1覆盖掉。换句话说如果你put(a1,b1);之后,用get方法h.get(a1)和h.get(a2)应该都能的到b1。如果你觉得这样说不太直观,你可以把a1、a2想象成两个String。但如果你要是不重写hashcode方法,则上述目标完成不了。因为,虽然我们认为a1和a2是相等的,并且equals的确如此,但问题是哈希表她不是按照equals来判断两个对象是否相等的!给哈希表一个键值,他会用hashcode方法取得这个键值的哈希码也就是hashcode值,把它作为实际的索引来管理整个表,如果你学过数据结构,应该知道管理的过程。反过来说,假如String类的作者仅仅重写equals而没重写hashcode方法,那么我们两次这样执行:h.put("aaa", b1); h.put("aaa", b2); 会在Hashtable中建立两个键值对,而h.get("aaa")则得不到b1或b2.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值