java中HashSet集合中存入同一个对象,为什么不会自动调用equals方法

qq_36080466 2016-10-30 10:59:23
哈希值相同就会调用equals方法比较内容,同一个对象按道理哈希值是相同的啊。如果都不调用equals方法那重写方法时if(this==obj)这句不是没意义了。以下是代码

import java.util.HashSet;
import java.util.Iterator;

class Bu1 {
private String atr;

public Bu1(String atr) {
super();
this.atr = atr;
}

public String getAtr() {
return atr;
}

public void setAtr(String atr) {
this.atr = atr;
}

public int hashCode() {
System.out.println("hashCode执行了");
return 1;

}

public boolean equals(Object obj) {
System.out.println("equals执行了");
return false;
}
public String toString() {
return atr;
}
}
public class abc {
public static void main(String[] args) {
HashSet hs=new HashSet();
Bu1 x=new Bu1("abc1");
Bu1 y=new Bu1("abc2");
hs.add(x);
hs.add(x);
hs.add(y);
Iterator it = hs.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
输出:hashCode执行了
hashCode执行了
hashCode执行了
equals执行了
abc1
abc2
存y时才调用了equals,存第二个x时没调用equals,哈希值都一样啊
...全文
276 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
ps45221 2016-10-31
  • 打赏
  • 举报
回复
其实
HashSet
的内部还是用
HashMap
来实现的,原理都差不多。 你这个程序的输出是这样执行的: 1、
hs.add(x);
的时候,它会计算hash值,会调用
hashCode
这个函数(输出了
hashCode执行了
),因为你这里重写了,所以hash值总为1,然后判断当前的hash表中有无和这个hash值一样的,这里因为是第一个,所以没有,添加进入hash表; 2、
hs.add(x);
的时候,一样计算hash值(输出
hashCode执行了
),过程和上面一样,hash值为1,然后判断当前hash表中有一个和这个hash值一样的,接下来继续判断,x和hash表中这个元素(hash值为1那个)是否相等(对象相等==),这里相等,所以直接返回,不添加。 3、
hs.add(y);
,和2流程基本一致,先判断hash值(输出了
hashCode执行了
),有相等,继续判断对象是否相等,发现不等,接下来就是你疑惑的重点了,它还会进行
equals()
方法(输出
equals执行了
),因为你重写了,总是返回false,所以这里判断不通过,添加。 下面就是关键地方的判断源代码:
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
e.hash:hash表中的那个hash值 hash:添加那个对象的hash值 key:添加的对象,这里就是x和y k = e.key:表中那个对象 关键在于 && 后面的那个表达式,如果 || 前面的
(k = e.key) == key
为true的后,java中是不会计算后面的那个的,就直接返回true了,因为不管后面的是true还是false,都不影响结果;反过来,如果前面的为false,才会计算后面那个。 这个就是你第二次添加x的时候,没有调用equals方法的原因所在!
说的比较啰嗦,但愿你能看懂~~~

62,628

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧