前言
十万个为什么之为什么要重写hashcode()方法???
equals比较的是对象的内容,==比较的是对象的地址。
equals()和hashcode()都是属于超类(Object)类中的基本方法,咱们先来看看equals()方法。
一、equals()方法原理
equals()方法默认是超类(Object)对象的一个基本方法,用于检测两个对象是否相等 (其实就是判断两个对象是否具有相同的引用)。
源码:
public boolean equals(Object obj) {
return (this == obj);
}
首先所有的对象都拥有标识(内存地址)和状态(数据/内容),同时==比较的是对象的地址,所以Object的equals()比较的是对象的地址。
二、equals()方法验证
定义一个实体类:
class User{
private String userName;
public User(String userName) {
this.userName = userName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
1.未重写equals方法
@Test
public void test01(){
User user1 = new User("詹三");
User user2 = new User("詹三");
// 结果
// false
System.out.println(user1.equals(user2));
// false
System.out.println(user1 == user2);
}
打印结果都是false,为什么?
结果就是上面所说:
①==比较的是对象的地址不是对象的内存。
②Object的equals()方法默认实现是==。
2.重写equals()方法
@Override
public boolean equals(Object obj) {
// return super.equals(obj);
// if (obj.getClass().equals(User.class)) {}
if (obj instanceof User) {
User c = (User) obj;
return userName == c.userName;
}
return false;
}
使用instanceof判断对象是否是User对象,再判断对象内容userName,相同为true否则为false
在测试一波,打印结果:
3.总结:
默认情况下从超类Object继承而来的equals方法与‘==’是完全等价的,比较的都是对象的内存地址,
但我们可以重写equals方法,使其按照我们的需求的方式进行比较。
三、为什么重写equals()的同时还得重写hashCode()
主要是运用到Key-Value集合中时,比如HashMap/HashTable/HaspSet, 将对象作为Key保存到集合中,在以“相等的”(equals()返回true)的另一个对象作为Key去查询对应的数据时, 根本找不到,为什么?
1.因为对象没有重写hashCode()方法,使用是Object默认的hashCode()方法,导致对象内容一致但是地址不一样。
2.Java API文档中关于hashCode方法有以下几点规定:
①在java应用程序执行期间,如果在equals方法比较中所用的信息没有被修改,那么在同一个对象上多次调用hashCode方法时必须一致地返回相同的整数。如果多次执行同一个应用时,不要求该整数必须相同。
②如果两个对象通过调用equals方法是相等的,那么这两个对象调用hashCode方法必须返回相同的整数。
③如果两个对象通过调用equals方法是不相等的,不要求这两个对象调用hashCode方法必须返回不同的整数。但是程序员应该意识到对不同的对象产生不同的hash值可以提供哈希表的性能。
1.未重写hashCode()方法
@Test
public void test02(){
User user1 = new User("詹三");
User user2 = new User("詹三");
// 结果
// true
System.out.println(user1.equals(user2));
System.out.println("user1.hashCode())>>>"+ user1.hashCode());
System.out.println("user2.hashCode())>>>"+ user2.hashCode());
// 以“相等的”(equals()返回true)的另一个对象作为Key去查询对应的数据
HashMap hashMap = new HashMap();
hashMap.put(user1, "詹三");
System.out.println("user1>>Key" + hashMap.get(user1));
System.out.println("user2>>Key" + hashMap.get(user2));
}
打印结果:
两个对象的hashcode值完全不一致,再以“相等的”(equals()返回true)的另一个对象作为Key去查询对应的数据为null,完全违反Java API文档中关于hashCode方法第二点规定。
2.重写hashCode()方法
这里直接使用Objects.hash(userName);
@Override
public int hashCode() {
// return super.hashCode();
return Objects.hash(userName);
}
再次测试:
两个对象的hashcode值一致,再以“相等的”(equals()返回true)的另一个对象作为Key去查询对应的数据一致。
2.总结
1.Map/sET等集合类型存放的对象必须是唯一的。
2.集合类判断对象是否相等,先equals()方法在hashCode()方法,必须都返回true。
3.由于Object默认的hashCode()方法返回的是对象的hash值,不是对象内容(参数值)的hash值,所以需要重写。
以上;感谢各位大大的耐心阅读~