瓜子网网站建设策划书百度一下你就知道官页
判断是否是相同对象时,hashcode和equals方法的调用顺序
- 先调用
hashcode()
方法,再调用equals()
方法 - 如果
hashcode()
方法得到的哈希值不同,那么两个对象一定不相同,不作后续判断 - 如果
hashcode()
方法得到的哈希值相同,那么还得判断equals()
方法,根据equals()
方法的返回值来具体判断两个对象是否相同 - 为什么哈希值相同,还得再判断equals方法?
可以去看一下我写的一般哈希 思想与模板代码 理解一下哈希的实现思路
可以发现会产生hash冲突的现象,即可能有几个key被存在了相同的hash位置,这时候仅凭借hash值是否相等,不能判断两个对象是否相等,这时候还得根据equals()
方法来验证判断下,可以理解为一个双保险。
如果想做一些特殊的去重操作,不同于一般的去重,该怎么有效利用hashcode和equals方法?
这里我给出自己在本科毕业设计中的一个样例。
问题需求
我想在HashSet
中存放一个类Comparison
,这个类的属性有两个对象se1
和se2
和他们之间的名称相似度NameSimilarity
和类别相似度CategorySimilarity
public class Comparison{private SE se1; //实体1private SE se2; //实体2private double NameSimilarity; //名称相似度private double CategorySimilarity; //类别相似度public Comparison(SE se1, SE se2, double nameSimilarity, double categorySimilarity) {this.se1 = se1;this.se2 = se2;NameSimilarity = nameSimilarity;CategorySimilarity = categorySimilarity;}
}
然后,定义两个Comparison
对象怎么才算重复呢?
如果一个Comparison
对象拥有实体(se1,se2)
,另一个Comparison
对象拥有(se2,se1)
或(se1,se2)
,则这两个Comparison
对象被认为是重复的,即交换对象里的两个SE
对象的位置仍然算是一个Comparison
对象。
重写hashcode和equals方法
@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Comparison that = (Comparison) o;return Double.compare(that.NameSimilarity, NameSimilarity) == 0 && Double.compare(that.CategorySimilarity, CategorySimilarity) == 0&& ( (se1.equals(that.se1)&&se2.equals(that.se2)) || (se1.equals(that.se2)&&se2.equals(that.se1)) );
}@Overridepublic int hashCode() {return Objects.hash(se1, se2, NameSimilarity, CategorySimilarity);//return Objects.hash(se1) + Objects.hash(se2) + Objects.hash(NameSimilarity, CategorySimilarity);// 让se1和se2的顺序对hash值没有影响就行
}
equals方法中的( (se1.equals(that.se1)&&se2.equals(that.se2)) |(se1.equals(that.se2)&&se2.equals(that.se1)) )
描述了上述逻辑。
但是发现这样写,仍然不对,没发发掘交换位置的情况,原来是因为交换位置后,Objects.hash(se1, se2, NameSimilarity, CategorySimilarity);
算出来的hashcode完全不一样了,根据前面讲的逻辑,一旦hashcode不一样,就不会再去判断equals方法。
优化
@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Comparison that = (Comparison) o;return Double.compare(that.NameSimilarity, NameSimilarity) == 0 && Double.compare(that.CategorySimilarity, CategorySimilarity) == 0&& ( (se1.equals(that.se1)&&se2.equals(that.se2)) || (se1.equals(that.se2)&&se2.equals(that.se1)) );
}@Overridepublic int hashCode() {//return Objects.hash(se1, se2, NameSimilarity, CategorySimilarity);return Objects.hash(se1) + Objects.hash(se2) + Objects.hash(NameSimilarity, CategorySimilarity);// 让se1和se2的顺序对hash值没有影响就行
}
return Objects.hash(se1) + Objects.hash(se2) + Objects.hash(NameSimilarity, CategorySimilarity);
这样写,可以让se1和se2的顺序对hash值没有影响,但也没有影响性能,也没有丧失hashcode的效果。