A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Akm 黑马帝   /  2012-2-11 08:54  /  4374 人查看  /  8 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 Akm 于 2012-2-13 09:00 编辑

java中为什么重写equals和hashcode的方法,什么时候重写?

评分

参与人数 1技术分 +1 收起 理由
唐秀启 + 1 请把求助改成已解决 谢谢合作

查看全部评分

8 个回复

倒序浏览
简单介绍Object中的equals()方法和HashCode()方法:java中的String,Integer这些类已经实现了equals和HashCode方法的重写,但是Object类中并没有重写
equals():
equals()方法,在这些类中equals()方法的实现是:
public boolean equals(Object obj){
     return(this == obj);
}
HashCode()方法
比较的是两个对象的内存地址,在Object中的定义是:public native int hashCode(); <完>
说明他只是一个本地方法,要了解HashCode就要了解java中集合,一般来说分为两类,一类是List,一类是Set。前者元素有序可以重复,后者无需不能重复。在Set中有HashMap,HashSet这些方法就是保证元素的不重复性。

两者关系:
要判断两个对象是否相等,就要重写equals()方法,具体的实现网上很多。重写equals()方法一般都要重写HashCode()方法,这是为了提高存储效率,上面说的HashCode可以保证相同的元素存储于相同的地址,理论上可以没有,但是如果没有,使用效率会大大降低。比如说String实现HashCode之后,相同的对象对应的地址相同,然后在进行equals比较,里面对象都存储在堆中的String Pool里面。
希望对你有所帮助

评分

参与人数 1技术分 +1 收起 理由
唐秀启 + 1

查看全部评分

回复 使用道具 举报
equals()和hashCode()都来自java.lang.Object.但在很多类中都进行了重写。

比如a.equals(b).仅当a和b的内存地址相等时,才返回true.当然如String等类已经对这个方法进行了重写,比较的就不再是内存地址了.

hashCode()的值也是与内存地址相关的.所以仅当内存地址相等时,hashCode才相等.同样很多类也重写了这个方法,还是以String为例:
public int hashCode() {
int h = hash;
if (h == 0) {
     int off = offset;
     char val[] = value;
     int len = count;

            for (int i = 0; i < len; i++) {
                h = 31*h + val[off++];
            }
            hash = h;
        }
        return h;
    }
这样就不再与内存地址相关了.这样做是为了保证用equals比较返回为true的两个对象,他们的hashCode是相同的.

所以一般重写equals的时候都会重写hashCode().

评分

参与人数 1技术分 +1 收起 理由
唐秀启 + 1

查看全部评分

回复 使用道具 举报
要求是需要重写的,实践上是可以不重写的,反正编译器不会报错,一般情况下也不回出问题,只要你不用类似于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.

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
我来说个简单点的答案:
从Object继承来的hashCode是基于对象的ID实现的。如果你重载了equals方法,而保留hashCode方法的实现不变,那么很可能某两个对象明明是“相等”,而hashCode却不一样。
这样,当你用其中的一个作为键保存到hashMap、hasoTable或hashSet中,再以“相等的”找另一个作为键值去查找他们的时候,则根本找不到。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
重写这两个方法主要是判断存储进去的两个对象是否是同一个对象,一般重写HashCode方法,是为了
提高效率的,但是equals方法也需要重写,如果两个对象用HashCode方法比较,若不同,则两个对象
一定不是同一个对象,equals比较的结果肯定也不同,如果用equals比较相同的话,HashCode比较的值
可能相同。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
蒙武辉 黑马帝 2012-2-11 13:03:47
7#
这是sun说的,看看Object#equals()和Object#hashCode()的文档,您就会明白了

  * Note that it is generally necessary to override the <tt>hashCode</tt>
  * method whenever this method is overridden, so as to maintain the
  * general contract for the <tt>hashCode</tt> method, which states
  * that equal objects must have equal hash codes.  

  * Returns a hash code value for the object. This method is  
  * supported for the benefit of hashtables such as those provided by  
  * <code>java.util.Hashtable</code>.

也就是说为了使用hashmap/hashtable等基于hashcode集合类能正常工作,做好在两个对象equals时,hashcode也要相等

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
Akm 黑马帝 2012-2-11 13:05:23
8#
  多谢回帖的朋友们。

  自己总结下:主要是为了“效率” 和 “安全性” 的缘故。 由于它的高度被使用率, 若 String允许被继承,可能会降低程序的性能,所以String被定义成final。

评分

参与人数 1技术分 +1 收起 理由
admin + 1 很客气,很认真。

查看全部评分

回复 使用道具 举报
Akm 黑马帝 2012-2-11 13:09:37
9#

RE: java中为什么重写equals和hashcode的方法?

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马