“equals”与“==”的区别-如何重写equals()和hashCode()方法
Posted hequnwang10
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“equals”与“==”的区别-如何重写equals()和hashCode()方法相关的知识,希望对你有一定的参考价值。
一、“equals”与“==”的区别
- 默认情况下也就是从超类Object继承而来的equals方法与"==“是完全等价的,比较的都是对象的内存地址(quals 比较的是值和地址,如果没有重写equals方法,其作用与”=="相同);
- 但我们可以重写equals方法,使其按照我们的需求的方式进行比较,如String类重写了equals方法,使其比较的是字符的序列,而不再是内存地址;
- hashCode用于散列数据结构中的hash值计算;
- equals两个对象相等,那hashcode一定相等,hashcode相等,不一定是同一个对象;
二、重写equals()和hashCode()方法
- equals - 保证比较对象是否是绝对相等的
- hashCode - 保证在最快的时间内判断两个对象是否相等,可能有误差值
1、hashCode()方法
- hashCode 的存在主要用于查找的快捷性,如 Hashtable, HashMap 等,hashCode 是用来在三列存储结构中确定对象的存储地址的。
- 如果两个对象相同,就是适用于 euqals(java.lang.Object) 方法,那么这两个对象的 hashCode一定相同。
- 如果对象的euqals 方法被重写,那么对象的 hashCode 也尽量重写,并且产生 hashCode 使用的对象,一定要和 equals 方法中使用的一致,否则就会违反上面提到的第二点。
- 两个对象的 hashCode 相同,并不一定表示这两个对象就相同,也就是不一定适用于equals() 方法,只能够说明这两个对象在三列存储结构中,如 Hashtable.,他们存在同一个篮子里。
首先举个例子来看一下equals()的方法的使用
package com.leetcode;
import java.util.Objects;
public class test
private int id;
public int getId()
return id;
public void setId(int id)
this.id = id;
public test(int id)
this.id = id;
public static void main(String[] args)
test t1 = new test(1);
test t2 = new test(1);
String str1 = "123";
String str2 = "123";
String str3 = "124";
System.out.println("str1地址:"+System.identityHashCode(str1));
System.out.println("str2地址:"+System.identityHashCode(str2));
System.out.println("str3地址:"+System.identityHashCode(str3));
System.out.println("str1.equals(str2)"+str1.equals(str2));
System.out.println("t1地址:"+System.identityHashCode(t1));
System.out.println("t2地址:"+System.identityHashCode(t2));
System.out.println("t1.equals(t2)"+t1.equals(t2));
System.out.println("t1 == t2"+(t1 == t2));
System.out.println("t1.hashCode()"+t1.hashCode());
System.out.println("t2.hashCode()"+t2.hashCode());
输出:
str1地址:23934342
str2地址:23934342
str3地址:22307196
str1.equals(str2)true
str1.equals(str3)false
t1地址:10568834
t2地址:21029277
t1.equals(t2)false
t1 == t2false
t1.hashCode()10568834
t2.hashCode()21029277
String类重写了equals方法,使其比较的是字符的序列,而不再是内存地址,所以我们发现str1和str2相等,但和str3不相等;
这里我们并没有重写equals()方法和hashCode()方法,打印t1地址和t2地址是不相等的,他们的hashCode也是不相等的,所以比较t1.equals(t2)时是不相等的。
2、只重写equals()方法
package com.leetcode;
import java.util.Objects;
public class test
private int id;
public int getId()
return id;
public void setId(int id)
this.id = id;
public test(int id)
this.id = id;
@Override
public boolean equals(Object o)
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
test test = (test) o;
return id == test.id;
public static void main(String[] args)
test t1 = new test(1);
test t2 = new test(1);
System.out.println("t1地址:"+System.identityHashCode(t1));
System.out.println("t2地址:"+System.identityHashCode(t2));
System.out.println("t1.equals(t2)"+t1.equals(t2));
System.out.println("t1 == t2"+(t1 == t2));
System.out.println("t1.hashCode()"+t1.hashCode());
System.out.println("t2.hashCode()"+t2.hashCode());
输出:
t1地址:23934342
t2地址:22307196
t1.equals(t2)true
t1 == t2false
t1.hashCode()23934342
t2.hashCode()22307196
虽然t1和t2的地址不相等,但是我们重写了equals()方法,使equals为比较两个的id值是否相等,所以比较之后t1.equals(t2)返回true。
但是这里的hashcode不相等,如果只重写equals而不重写HashCode会有什么影响?
两个相等的对象必须具有相等的散列码(Java关键约定
举一个例子:
如果一个只重写了equals(比较所有属性是否相等)的类 new 出了两个属性相同的对象。这时可以得到的信息是这个
属性相同的对象地址肯定不同,但是equals是true,hashCode返回的是不相等的(一般不会出现hash碰撞)。
也就是说这个类对象违背了Java对于两个对象相等的约定。违背约定的原因是 可靠的equals判断两个对象是相等
的,但是他们两个的散列码确是不相等的。
总结:
- equals 为 true , hashCode 必须相等
- hashCode 相等时 , equals 可以不用为 true (也就是hash碰撞的时候)
不写hashCode()的影响:
- 两个所有属性都相等的对象,但是地址不同。没重写hashCode时,p.hash == hash 一定不相等。但是逻辑上这两个对象是相等的,并且equals也是相等的。
- 这就会导致,HashMap里面本来有这个key,但是你告诉我没有,导致了put操作成功。逻辑上是不符合规范的,get时取出来的也可能是自己另一个的value。
3、重写equals()方法和hashCode()方法
package com.leetcode;
import java.util.Objects;
public class test
private int id;
public int getId()
return id;
public void setId(int id)
this.id = id;
public test(int id)
this.id = id;
@Override
public boolean equals(Object o)
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
test test = (test) o;
return id == test.id;
@Override
public int hashCode()
return Objects.hash(id);
public static void main(String[] args)
test t1 = new test(1);
test t2 = new test(1);
System.out.println("t1地址:"+System.identityHashCode(t1));
System.out.println("t2地址:"+System.identityHashCode(t2));
System.out.println("t1.equals(t2)"+t1.equals(t2));
System.out.println("t1 == t2"+(t1 == t2));
System.out.println("t1.hashCode()"+t1.hashCode());
System.out.println("t2.hashCode()"+t2.hashCode());
输出:
t1地址:23934342
t2地址:22307196
t1.equals(t2)true
t1 == t2false
t1.hashCode()32
t2.hashCode()32
以上是关于“equals”与“==”的区别-如何重写equals()和hashCode()方法的主要内容,如果未能解决你的问题,请参考以下文章