问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
你好,欢迎来到懂视!登录注册
当前位置: 首页 - 正文

hashmap中equals() 和hashcode(),请教

发布网友 发布时间:2022-07-11 19:28

我来回答

2个回答

热心网友 时间:2022-07-11 19:48

//看下这篇文章

众所周之,String 、Math、还有Integer、Double。。。。等这些封装类重写了Object中的equals()方法,让它不再比较句柄(引用),而是比较对象中实际包含的整数的值,即比较的是内容。

而Object的equals()方法比较的是地址值。

一般来说,如果你要把一个类的对象放入容器中,那么通常要为其重写equals()方法,让他们比较地址值而不是内容值。特别地,如果要把你的类的对象放入散列中,那么还要重写hashCode()方法;要放到有序容器中,还要重写compareTo()方法。

本人愚见,只有用到Hashtable、HashMap、HashSet、LinkedHashMap等时才要注意hashcode,其他地方hashcode无用。

为什么要重写hashCode方法?

我们应该先了解java判断两个对象是否相等的规则。

在java的集合中,判断两个对象是否相等的规则是:

首先,判断两个对象的hashCode是否相等

如果不相等,认为两个对象也不相等
如果相等,则判断两个对象用equals运算是否相等
如果不相等,认为两个对象也不相等
如果相等,认为两个对象相等

我们在equals方法中需要向下转型,效率很低,所以先判断hashCode方法可以提高效率

--------------------------------------

今天下午研究了半天hashcode()和equals()方法,终于有了一点点的明白,写下来与大家分享(zhaoxudong 2008.10.23晚21.36)。
1. 首先equals()和hashcode()这两个方法都是从object类中继承过来的。
equals()方法在object类中定义如下:
public boolean equals(Object obj) {
return (this == obj);
}
很明显是对两个对象的地址值进行的比较(即比较引用是否相同)。但是我们必需清楚,当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法。比如在String类中如下:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
很明显,这是进行的内容比较,而已经不再是地址的比较。依次类推Double、Integer、Math。。。。等等这些类都是重写了equals()方法的,从而进行的是内容的比较。当然了基本类型是进行值的比较,这个没有什么好说的。
我们还应该注意,Java语言对equals()的要求如下,这些要求是必须遵循的:
• 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。
• 反射性:x.equals(x)必须返回是“true”。
• 类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。
• 还有一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
• 任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。
以上这五点是重写equals()方法时,必须遵守的准则,如果违反会出现意想不到的结果,请大家一定要遵守。
2. 其次是hashcode() 方法,在object类中定义如下:
public native int hashCode();
说明是一个本地方法,它的实现是根据本地机器相关的。当然我们可以在自己写的类中覆盖hashcode()方法,比如String、Integer、Double。。。。等等这些类都是覆盖了hashcode()方法的。例如在String类中定义的hashcode()方法如下:
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;
}
解释一下这个程序(String的API中写到):
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
使用 int 算法,这里 s[i] 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希码为 0。)

3.这里我们首先要明白一个问题:
equals()相等的两个对象,hashcode()一定相等;
equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。
反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。解释下第3点的使用范围,我的理解是在object、String等类中都能使用。在object类中,hashcode()方法是本地方法,返回的是对象的地址值,而object类中的equals()方法比较的也是两个对象的地址值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了;在String类中,equals()返回的是两个对象内容的比较,当两个对象内容相等时,
Hashcode()方法根据String类的重写(第2点里面已经分析了)代码的分析,也可知道hashcode()返回结果也会相等。以此类推,可以知道Integer、Double等封装类中经过重写的equals()和hashcode()方法也同样适合于这个原则。当然没有经过重写的类,在继承了object类的equals()和hashcode()方法后,也会遵守这个原则。

4.谈到hashcode()和equals()就不能不说到hashset,hashmap,hashtable中的使用,具体是怎样呢,请看如下分析:
Hashset是继承Set接口,Set接口又实现Collection接口,这是层次关系。那么hashset是根据什么原理来存取对象的呢?
在hashset中不允许出现重复对象,元素的位置也是不确定的。在hashset中又是怎样判定元素是否重复的呢?这就是问题的关键所在,经过一下午的查询求证终于获得了一点启示,和大家分享一下,在java的集合中,判断两个对象是否相等的规则是:
1),判断两个对象的hashCode是否相等
如果不相等,认为两个对象也不相等,完毕
如果相等,转入2)
(这一点只是为了提高存储效率而要求的,其实理论上没有也可以,但如果没有,实际使用时效率会大大降低,所以我们这里将其做为必需的。后面会重点讲到这个问题。)
2),判断两个对象用equals运算是否相等
如果不相等,认为两个对象也不相等
如果相等,认为两个对象相等(equals()是判断两个对象是否相等的关键)
为什么是两条准则,难道用第一条不行吗?不行,因为前面已经说了,hashcode()相等时,equals()方法也可能不等,所以必须用第2条准则进行*,才能保证加入的为非重复元素。
比如下面的代码:

public static void main(String args[]){
String s1=new String("zhaoxudong");
String s2=new String("zhaoxudong");
System.out.println(s1==s2);//false
System.out.println(s1.equals(s2));//true
System.out.println(s1.hashCode());//s1.hashcode()等于s2.hashcode()
System.out.println(s2.hashCode());
Set hashset=new HashSet();
hashset.add(s1);
hashset.add(s2);

Iterator it=hashset.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
最后在while循环的时候只打印出了一个”zhaoxudong”。
输出结果为:false
true
-967303459
-967303459
这是因为String类已经重写了equals()方法和hashcode()方法,所以在根据上面的第1.2条原则判定时,hashset认为它们是相等的对象,进行了重复添加。
但是看下面的程序:
import java.util.*;
public class HashSetTest
{
public static void main(String[] args)
{
HashSet hs=new HashSet();
hs.add(new Student(1,"zhangsan"));
hs.add(new Student(2,"lisi"));
hs.add(new Student(3,"wangwu"));
hs.add(new Student(1,"zhangsan"));

Iterator it=hs.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
class Student
{
int num;
String name;
Student(int num,String name)
{
this.num=num;
this.name=name;
}
public String toString()
{
return num+":"+name;
}
}
输出结果为:
1:zhangsan
1:zhangsan
3:wangwu
2:lisi
问题出现了,为什么hashset添加了相等的元素呢,这是不是和hashset的原则违背了呢?回答是:没有
因为在根据hashcode()对两次建立的new Student(1,"zhangsan")对象进行比较时,生成的是不同的哈希码值,所以hashset把他当作不同的对象对待了,当然此时的equals()方法返回的值也不等(这个不用解释了吧)。那么为什么会生成不同的哈希码值呢?上面我们在比较s1和s2的时候不是生成了同样的哈希码吗?原因就在于我们自己写的Student类并没有重新自己的hashcode()和equals()方法,所以在比较时,是继承的object类中的hashcode()方法,呵呵,各位还记得object类中的hashcode()方法比较的是什么吧!!
它是一个本地方法,比较的是对象的地址(引用地址),使用new方法创建对象,两次生成的当然是不同的对象了(这个大家都能理解吧。。。),造成的结果就是两个对象的hashcode()返回的值不一样。所以根据第一个准则,hashset会把它们当作不同的对象对待,自然也用不着第二个准则进行判定了。那么怎么解决这个问题呢??
答案是:在Student类中重新hashcode()和equals()方法。
例如:
class Student
{
int num;
String name;
Student(int num,String name)
{
this.num=num;
this.name=name;
}
public int hashCode()
{
return num*name.hashCode();
}
public boolean equals(Object o)
{
Student s=(Student)o;
return num==s.num && name.equals(s.name);
}
public String toString()
{
return num+":"+name;
}
}
根据重写的方法,即便两次调用了new Student(1,"zhangsan"),我们在获得对象的哈希码时,根据重写的方法hashcode(),获得的哈希码肯定是一样的(这一点应该没有疑问吧)。
当然根据equals()方法我们也可判断是相同的。所以在向hashset集合中添加时把它们当作重复元素看待了。所以运行修改后的程序时,我们会发现运行结果是:
1:zhangsan
3:wangwu
2:lisi
可以看到重复元素的问题已经消除。
关于在hibernate的pojo类中,重新equals()和hashcode()的问题:
1),重点是equals,重写hashCode只是技术要求(为了提高效率)
2),为什么要重写equals呢,因为在java的集合框架中,是通过equals来判断两个对象是否相等的
3),在hibernate中,经常使用set集合来保存相关对象,而set集合是不允许重复的。我们再来谈谈前面提到在向hashset集合中添加元素时,怎样判断对象是否相同的准则,前面说了两条,其实只要重写equals()这一条也可以。
但当hashset中元素比较多时,或者是重写的equals()方法比较复杂时,我们只用equals()方法进行比较判断,效率也会非常低,所以引入了hashcode()这个方法,只是为了提高效率,但是我觉得这是非常有必要的(所以我们在前面以两条准则来进行hashset的元素是否重复的判断)。
比如可以这样写:
public int hashCode(){
return 1;}//等价于hashcode无效
这样做的效果就是在比较哈希码的时候不能进行判断,因为每个对象返回的哈希码都是1,每次都必须要经过比较equals()方法后才能进行判断是否重复,这当然会引起效率的大大降低。
我有一个问题,如果像前面提到的在hashset中判断元素是否重复的必要方法是equals()方法(根据网上找到的观点),但是这里并没有涉及到关于哈希表的问题,可是这个集合却叫hashset,这是为什么??
我想,在hashmap,hashtable中的存储操作,依然遵守上面的准则。所以这里不再多说。这些是今天看书,网上查询资料,自己总结出来的,部分代码和语言是引述,但是千真万确是自己总结出来的。有错误之处和不详细不清楚的地方还请大家指出,我也是初学者,所以难免会有错误的地方,希望大家共同讨论。

参考资料:http://blog.sina.com.cn/s/blog_5671e70e0100bgil.html

热心网友 时间:2022-07-11 19:49

1。HashMap中key的默认是使用Int的包装类,当你要使用自定义的类作为key的时候才要重载equals(),hashcode()方法.
原因如下:HashMap是使用散列的方法来进行快速查找.当进行查找的时候先将你hashmap中的key调用hashcode()方法得到一个散列值,所以这时就需要你对hashcode()方法进行重载,同时这个值对应的是一个LinkedList数组的下标,而这个LinkedList数组中存的就是你的value对象,然后hashmap调用equals方法对LinkedList数组中的value对象值进行比较。而默认的equals()方法是对对象的引用的比较,所以这是你同样要重载equals()方法.
2。set只是不允许重复,不用重载.
3.只判断对象equals就OK.
hashmap中equals() 和hashcode(),请教

hashmap中equals() 和hashcode(),请教 在thinkinginjava中hashmap中说,如果key是自定义的类,那么必须得重载equals()和hashcode()两个方法,书中说的我没理解太清楚,所以我有了如下这么几个问题:1)如果要比较key是否相... 在thinking in java中hashmap中说,如果key是自定义的类,那么必须得重载equals()和hashco...

java里equals和hashCode之间什么关系

equals()主要用于用户比较对象内容的相似性,比如在集合中判断两个对象是否应该视为同一个。而hashCode()则是为了优化哈希表(如HashMap)的性能,通过计算对象的地址或内容来生成一个整数,用于快速定位存储位置。尽管equals()方法的实现要求,如果两个对象相等,它们的hashCode()应返回一致的结果,但反之...

说说hashCode() 和 equals() 之间的关系?

两种情况下的hashCode()和equals()关系如下:1. 当对象不会用于散列表(如HashSet, HashMap, Hashtable)时,hashCode()和equals()没有直接关系。hashCode()的作用仅限于对象在内存中的定位,与相等判断无关。例如,创建对象用于数组或其他数据结构时,hashCode()的值决定了对象在数组中的位置,但与eq...

Equal()和HashCode的相关理解

在深入理解Java编程时,equals()和hashCode()是两个关键的概念,尤其在处理collections时。下面将详细阐述它们的作用和使用规则。所有Java类都直接或间接继承自Object类,这个父类提供了equals()和hashCode()方法。在实际应用中,如添加元素到HashSet或HashMap等基于哈希的集合时,这两个方法至关重要。如果...

java里equals和hashCode之间什么关系

equals与hashcode的关系是:两个对象在equals相等的情况下,hashcode有可能相等也有可能不相等,而两个对象在hashcode不相等的情况下,equals也必定不相等。理解equals的应用:它是用于用户在进行对比的时候,这个时候对比的是内容是否相等理解hashcode的应用:例如set集合,它的不可重复,进行对比的便是hashcode...

equals和hashcode谁的效率更高?为什么?谢谢解答

其实不能说谁比谁高,是hashcode+equals 效率最高 比如在hashset中,已经有1000个数据 如果只用equals,插入第1001个数据时,需要依次和前1000个比 如果用hashcode,可将前面数据的范围缩小(不同对象的hashcode可能相等),这样如果hashcode如果不同,直接false,相同时调用equals方法进一步确认 ...

如何正确的重写equals 和 hashCode方法

如果只重写hashcode()不重写equals()方法,当比较equals()时只是看他们是否为同一对象(即进行内存地址的比较),所以必定要两个方法一起重写。HashMap用来判断key是否相等的方法,其实是调用了HashSet判断加入元素是否相等。引用别人说的一段话哈~一般来说,如果你要把一个类的对象放入容器中,那么通常要...

java中hashcode()方法有什么作用呢?最好举个例子啊!

hashcode方法一般用户不会去调用,比如在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了hashcode这个方法,而且也用到了equals方法。这里不可以重复是说equals和hashcode只要有一个不等就可以了!所以简单来讲,hashcode相当于是一个对象的编码,就好像文件中的md5,他和equals不同...

hash code、equals和“==”三者的关系

你想通过一个object的key来拿hashmap的value,hashmap的工作方法是,通过你传入的object的hashcode在内存中找地址,当找到这个地址后再通过equals方法来比较这个地址中的内容是否和你原来放进去的一样,一样就取出value。所以这里要匹配2部分,hashcode和equals 但假如说你new一个object作为key去拿value是永远...

Equals And HashCode 梳理

总的来讲: hashcode的产生是为了hashmap等使用到hashcode的散列存储结构服务的。 hashcode有如下三个性质: 性质1 :一致性:对于同一对象,多次调用hashcode()应返回相同的Integer。 性质2 :equals相等,则hashCode必须相等。 性质3 :equals不等,hashCode不是必须不等。了解了hashcode...

声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。
E-MAIL:11247931@qq.com
再见了,企鹅电竞!陪跑好多年,终要说再见! 吕祖灵签六十九签解签,吕祖灵签六十签解签 作文五年级下册《小嘎子和胖墩儿比赛摔跤》续写 我爸爸写诗词时,押的韵竟然是“mai”、“mei”。我想问一下,有这样押韵... 出生刚一周,请网友们给想个名字,爸爸姓罗。好听就行,重点得押韵哦,谢谢... 为什么太阳落山时比正午时的要大? 猫突然用头蹭人还咕噜咕噜怎么回事 会把主人当配偶吗 有关《两小儿辩日》中的一个科学问题 颈椎检查多少钱 磁共振成像检查多少钱 请问java的hashmap容器中,每个对象的hashcode都不相等,它的存取效率是高还是低呢? hashmap需要重写hashcode和equals吗 hashmap中为什么对hashcode使用hash方法 英语小故事 有3个时态以上 请讲一个英语的小故事,最好是配图。不配也可以,不要太多,不要太少……十个、二十个单词差不多(36页) 经营地址异常有什么影响 一句话让女朋友哭 关于李煜的月的诗句 李煜写的有关月亮的诗词 上汽大通g50手动畅游A和畅游b怎么区分? 比较好的经营和管理的书有那些? 关于水果蔬菜店的管理与经营看什么书 和继父吵架后怎么办? 和继父吵架怎么办 要赶我走 妈妈和后爸打架了,作为女儿的我该怎么办? 继父与儿子争吵打架可不可以立案? 梦到儿子和继父打架 母亲和继父打架斗殴怎么办??要帮忙吗??? 组合家庭三十多继子和继父发生冲途打伤继父,儿子该如何办? 女儿跟继父动手打架了。女儿要走,我这个妈妈该怎么办? 芸芸众生相识就是缘分下一句怎么接? 狂的拼音 韩国电影片段一男警察打倒一群男人,最后被女头目差点勒死什么电影 15 有一个韩国电影的一个片段,一个穿白裙子的女子在黑暗中跑着,没穿鞋子, 然后突然一个男人把她抱 火影里这人是谁 桶装水太重,老人家如何搬上楼,家里没男丁,有什么科技能够解决的吗? 私人合同需要盖章吗 买卖合同纠纷属于债权吗 买卖合同是债权吗 《狂骨之梦魍魉之匣姐妹篇》epub下载在线阅读,求百度网盘云资源 安徽文化特有 哪些 安徽有哪些文人墨客? 为了使身体健康,都需要注意哪些方面? 英文26个字母的正确读音和正确写法,你学会了吗 写一篇成长日记450字如劳动 蒜苗的七天成长日记450字? 成长日记滑雪450字怎么写? 酒店管理知识的网站有哪些啊? 告诉我最好的酒店管理知识网站 我需要一些旅游管理、酒店管理方面的资料,有什么好的网站推荐的吗?
  • 焦点

最新推荐

猜你喜欢

热门推荐