Java equals()和hashCode()的区别和使用
Java equals()和hashCode()的区别和使用
目录
equals()和hashCode()的作用
用来比较两个对象实例是否相同
equals()和hashCode()的区别和使用
equals()和hashCode()的区别
equals()方法:一般两个对象实例使用equals()方法来比较彼此是否相同,我们可以在类中重写此方法,用来自定义生成的两个对象实例见如何才能是相同的,比如说比较对象的某一个属性,此属性值相同,则对象实例也相同,都是可以自定义的,equals()方法可以用于比较复杂的对比,因此equals()方法效率比较低。
hashCode()方法:hashCode()是直接比较生成的hash值,值相同,则对象实例也相同,效率比较高。
equals()和hashCode()的使用
既然hashCode()方法效率比较高,那么为什么不直接只用hashCode()方法,而还要用equals()方法呢?
因为不同的对象他们生成的hashCode有可能是一样的,所以这时使用hashCode()方法会产生错误的结果。
那么我们可以得到一个结论:
1.equals()方法结果相等的两个对象实例,其hashCode()方法也会相等;
2.hashCode()方法相等的两个对象实例,其equals()方法的结果不一样相等。
如果需要大量且快速比较对象实例的场景的话,则可以先使用hashCode()去比较,如果hashCode()不相等,则这两个对象实例一定不相等(就可以不用使用equals()去做比较了,节省时间,提高效率);如果hashCode()相等,则再使用equals()做比较。这样既可以提高效率,又可以保证准确。
代码实例
首先定义三个类
/**
* @Date 2020/7/30 9:38
* @Author hezhan
* 测试在重写equals和hasCode的方法下对象的对比
*/
public class TestEqualsWithCover {
private String name;
private String code;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestEqualsWithCover that = (TestEqualsWithCover) o;
return name.equals(that.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
/**
* @Date 2020/7/30 9:35
* @Author hezhan
* 测试在不重写equals和hasCode的情况下的对象的比较
*/
public class TestEqualsWithoutCover {
private String name;
private String code;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
/**
* @Date 2020/7/30 9:54
* @Author hezhan
* 测试在重写equals方法但没有重写hasCode方法下的对象对比
*/
public class TestEqualsWithoutHasCode {
private String name;
private String code;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestEqualsWithoutHasCode that = (TestEqualsWithoutHasCode) o;
return name.equals(that.name);
}
}
然后进行测试
/**
* 测试下没有重写equals和hasCode方法的两个对象实例的比较,
* 并测试将两个对象实例放入集合中,查看是否会覆盖
*/
TestEqualsWithoutCover t1 = new TestEqualsWithoutCover();
t1.setName("he");
t1.setCode("zhan");
TestEqualsWithoutCover t2 = new TestEqualsWithoutCover();
t2.setName("he");
t2.setCode("zhan");
HashSet<TestEqualsWithoutCover> s1 = new HashSet<>();
s1.add(t1);
s1.add(t2);
List<TestEqualsWithoutCover> l1 = new ArrayList<>();
l1.add(t1);
l1.add(t2);
Map<TestEqualsWithoutCover, Object> m1 = new HashMap<>();
m1.put(t1, "");
m1.put(t2, "123");
System.out.println("没有重写equals和hasCode方法的对象实例使用==的比较结果:" + (t1 == t2));
System.out.println("没有重写equals和hasCode方法的对象实例使用equals的比较结果:" + (t1.equals(t2)));
System.out.println("set size:" + s1.size());
System.out.println("list size:" + l1.size());
System.out.println("map size:" + m1.size());
/**
* 测试下只重写了equals的两个对象实例的比较,
* 并测试将两个对象实例放入集合中,查看是否会覆盖
*/
TestEqualsWithoutHasCode h1 = new TestEqualsWithoutHasCode();
h1.setName("he");
h1.setCode("zhan");
TestEqualsWithoutHasCode h2 = new TestEqualsWithoutHasCode();
h2.setName("he");
h2.setCode("xx");
HashSet<TestEqualsWithoutHasCode> s2 = new HashSet<>();
s2.add(h1);
s2.add(h2);
List<TestEqualsWithoutHasCode> l2 = new ArrayList<>();
l2.add(h1);
l2.add(h2);
Map<TestEqualsWithoutHasCode, Object> m2 = new HashMap();
m2.put(h1, "xx");
m2.put(h2, "123");
System.out.println("只重写了equals方法的两个对象实例使用=的比较结果:" + (h1 == h2));
System.out.println("只重写了equals方法的两个对象实例使用equals的比较结果:" + (h1.equals(h2)));
System.out.println("set size:" + s2.size());
System.out.println("list size:" + l2.size());
System.out.println("map size:" + m2.size());
/**
* 测试重写了equals和hasCode方法的两个对象实例的比较,
* 并测试将两个对象实例放入集合中,查看是否会覆盖
*/
TestEqualsWithCover w1 = new TestEqualsWithCover();
w1.setName("he");
w1.setCode("zhan");
TestEqualsWithCover w2 = new TestEqualsWithCover();
w2.setName("he");
w2.setCode("xx");
Set<TestEqualsWithCover> s3 = new HashSet<>();
s3.add(w1);
s3.add(w2);
List<TestEqualsWithCover> l3 = new ArrayList<>();
l3.add(w1);
l3.add(w2);
Map<TestEqualsWithCover, Object> m3 = new HashMap<>();
m3.put(w1, "12");
m3.put(w2, "123");
System.out.println("重写了equals和hasCode方法的两个对象实例使用=的比较结果:" + (w1 == w2));
System.out.println("重写了equals和hasCode方法的两个对象实例使用equals的比较结果:" + (w1.equals(w2)));
System.out.println("set size:" + s3.size());
System.out.println("list size:" + l3.size());
System.out.println("map size:" + m3.size());
我们看测试结果:
得到的结论
1、equals()方法可以自定义重写,用来比较两个对象实例是否相等。
2、hashCode()方法在一些需要快速比较的集合中使用的比较多,比如HashSet、HashMap、HashTable中,在这些保证数据唯一的集合中,会先用hashCode()来比较集合中已有的对象,然后再用equals()来比较。
本文地址:https://blog.csdn.net/weixin_43827693/article/details/107685236
推荐阅读
-
MySQL中datetime和timestamp的区别及使用详解
-
java中hashCode和equals什么关系,hashCode到底怎么用的
-
Java中HashMap和TreeMap的区别深入理解
-
浅谈Java异常的Exception e中的egetMessage()和toString()方法的区别
-
Java线程Run和Start的区别
-
详解java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)
-
32位和64位CPU的操作系统的区别 判断、使用建议
-
Java常见面试问题: equals()与hashCode()的使用
-
SQL2005中char nchar varchar nvarchar数据类型的区别和使用环境讲解
-
Java自学-集合框架 HashMap和Hashtable的区别