equals的hashcode,hashcode和equals的区别 简书
Java的基类对象提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希代码。Equals()和hashCode()不是最终方法,两者都可以被覆盖。
如何解决写爬虫IP受阻的问题?立即使用。
本文介绍了使用和改写这两种方法时应注意的一些问题。
一、equal()方法
Object类中的equals()方法实现如下:
公共布尔等于(对象对象){
return(this==obj);
}从这个实现可以看出,Object class的实现采用了区分度最高的算法,即只要两个对象不是同一个对象,那么equals()就必须返回false。
虽然我们可以在定义类时覆盖equals()方法,但是有一些注意事项;JDK描述了实现equals()方法时应该遵守的约定:
(1)自反性:x.equals(x)必须返回true。
(2)对称性:x.equals(y)和y.equals(x)的返回值必须相等。
(3)传递性:如果x.equals(y)为真,y.equals(z)为真,那么x.equals(z)一定为真。
(4)一致性:如果equals()中对象X和Y使用的信息没有变化,那么x.equals(y)的值总是相同的。
(5)非空:如果x不为空,y为空,则x.equals(y)必须为假。
二、hashCode()方法
1、Object的hashCode()
Object类中hashCode()方法的声明如下:
public native int hashCode();可以看出hashCode()是原生方法,返回值类型是shaping这个原生方法实际上是将对象在内存中的地址作为哈希代码返回,这样可以保证不同对象的返回值是不同的。
类似于equals()方法,hashCode()方法可以被覆盖。JDK解释了hashCode()方法的作用以及实现时的注意事项:
(1)hashCode()在哈希表中工作,比如java.util.HashMap
(2)如果equals()中对象使用的信息都没有改变,那么hashCode()的值总是相同的。
(3)如果用equals()方法判断两个对象相等,hashCode()方法也应该相等。
(4)如果用equals()方法判断两个对象不相等,不要求hashCode()也一定不相等;但是,开发人员应该认识到,哈希表的性能可以通过不相等的对象产生不同的hashCode来提高。
2、hashCode()的作用
一般来说,hashCode()在哈希表中起作用,比如HashSet、HashMap等。
当我们将一个object对象添加到哈希表(如HashSet、HashMap等)时。),我们首先调用hashCode()方法计算对象的hash码,通过它可以直接定位对象在哈希表中的位置(一般情况下hash码结转哈希表大小)。如果这个位置没有对象,可以直接把对象插入这个位置;如果这个位置有对象(可能有多个对象,用链表实现),调用equals()方法比较这些对象是否等于对象,如果相等,则不需要保存对象;如果没有,将该对象添加到链表中。
这就解释了为什么equals()相等,则hashCode()必须相等。如果两个对象equals()相等,那么它们在一个哈希表中应该只出现一次(比如HashSet、HashMap等。);如果hashCode()不相等,那么它们将被散列到哈希表中的不同位置,这将出现不止一次。
实际上,在JVM中,加载的对象在内存中包括三个部分:对象头、实例数据和填充。其中,对象头包括指向对象类型的指针和标记字,以及MarkWord中除了包含对象的GC分代年龄信息、加锁状态信息外,还包括了对象的hashcode;实例数据是对象真正存储的有效信息;填充只是作为一个占位符,因为HotSpot要求对象的起始地址必须是8字节的整数倍。
三、String中equals()和hashCode()的实现
String类中的相关实现代码如下:
私有最终字符值[];
私有int哈希;//默认为0
公共布尔等于(对象与对象){
if (this==anObject) {
返回true
}
if(字符串的对象实例){
String another String=(String)an object;
int n=value.length
if(n==another string . value . length){
char v1[]=值;
char v2[]=another string . value;
int I=0;
而(n -!=0) {
if (v1[i]!=v2[i])
返回false
我;
}
返回true
}
}
返回false
}
public int hashCode() {
int h=hash
if (h==0 value.length 0) {
char val[]=value;
for(int I=0;i value.lengthi ) {
h=31 * h val[I];
}
hash=h;
}
返回h;
}通过代码可以看到以下几点:
1.String的数据是final,即String对象一旦创建,就不能修改;如String s= hellos= world语句,当执行s=world 时,不是string对象的值更改为 world ,而是创建一个新的String对象,s引用指向新对象。
2.String类将hashCode()的结果缓存为一个哈希值,以提高性能。
3.String对象equals()相等的条件是,它们都是长度相同、字符串值完全相同的String对象;它们不需要是相同的对象。
4.String的hashCode()的计算公式为:s [0] * 31 (n-1) s [1] * 31 (n-2).标准[名词]1
在hashCode()的计算中使用数字31的原因如下:
1.使用质数计算散列码。因为素数的特性,它乘以其他数后,计算结果唯一的概率更大,哈希冲突的概率更小。
2.使用的素数越大,哈希碰撞的概率越小,但计算速度越慢;31是哈希碰撞和性能的折中,实际上是实验观察的结果。
3.JVM会自动优化31: 31 * i==(i 5)-i
四、如何重写hashCode()
本节首先介绍重写hashCode()方法时应遵循的原则,然后介绍一般的hashCode()重写方法。
1、重写hashcode()的原则
从前面的描述中,我们知道重写hashCode需要遵循以下原则:
(1)如果equals()方法被覆盖,检查条件“如果两个对象被equals()方法判断为相等,hashCode()方法也应该相等”是否成立,如果不成立,重写hashCode()方法。
(2)2)hashCode()方法不能太简单,否则哈希冲突太多。
(3)3)hashCode()方法不能太复杂,否则计算复杂度太高,影响性能。
2、hashCode()重写方法
755-79000提出了一种简单通用的hashCode算法。
a、初始化一个整形变量,给这个变量赋一个非零常数值,比如int result=17
b、选择equals方法中所有用于比较的字段(之所以只选择equals()中使用的字段,是为了保证上述原则的第1条),然后计算每个字段的属性:
(1)如果是布尔值,计算f?1:0
(2)如果是byte\char\short\int,计算(int) f。
(3)如果是长整型值,计算(int) (f (f 32))
(4)如果是浮点值,则计算float.floatpointbits (f)
(5)如果是double值,计算Double.doubleToLongBits(f),然后返回的结果是long,再用规则(3)处理long得到int。
(6)如果是对象应用,如果equals方法中采用递归调用的比较方法,那么hashCode中也采用递归调用hashCode的方法。否则,您需要计算该字段的范式。例如,当该字段的值为null时,hashCode值为0。
(7)如果是数组,那么每个元素都需要作为一个单独的域来对待。Java.util.Arrays.hashCode方法包括八种基本类型数组和引用数组的hashCode计算。算法同上。
c、最后将各个域的哈希码合并到对象的哈希码中。
下面的例子说明了这一点。在这个例子中,Person类覆盖了equals()方法和hashCode()方法。因为equals()方法中只使用了姓名和年龄字段,所以hashCode()方法中只计算姓名和年龄字段。
对于String类型的域名,直接使用String的hashCode()方法;对于int类型的age字段,直接使用其值作为字段的哈希。
公共类人员{
私有字符串名称;
私人年龄;
私有布尔性别;
公共人物(){
super();
}
公共字符串getName() {
返回名称;
}
public void setName(字符串名){
this.name=name
}
public int getAge() {
回归年龄;
}
公共无效存储(整数){
this.age=年龄;
}
public boolean isGender() {
返回性别;
}
public void setGender(布尔性别){
this.gender=性别;
}
@覆盖
公共布尔等于(对象另一个){
如果(这==另一个){
返回真实的
}
如果(另一个人的实例){
Person另一个人=(人)另一个;
if (this.getName().等于(另一个人。getname())这个。getage()==另一个人。getage()){
返回真实的
}否则{
返回错误的
}
}
返回错误的
}
@覆盖
public int hashCode() {
int hash=17
hash=hash * 31 getName().hashCode();
hash=hash * 31 getAge();
返回哈希;
}
}推荐教程:java教程以上就是等于()方法和哈希码()方法(详细介绍)的详细内容,更多请关注我们其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。