|
注:本文的所有验证在文章最后
如果您愿意相信我的话,请静下心来,慢慢阅读,一定会解除您心中的些许疑惑
一、原生的hashCode与equals是什么样的
原生hashCode值为内存地址(未考正)
原生equals比较的是内存地址
二、什么时候重写equals?
答:比较两个实例是否相等时重写equals()。
equals()用于比较两个实例是否相等,两实例属性对应相等 => 两实例相等
只单纯比较两个同类型实例是否相等时只重写equals()就可以。作者觉得 "为什么重写equals()一定要重写hashCode”这种标题并不合理。
三、什么时候重写hashCode?
答:自定义类型作为HashMap的key
我相信还有其他情况需要重写hashCode,作者愚笨,暂时还不了解其他的情况,请谅解。
四、重写hashCode与equals的例子
自定义类型作为HashMap的key,没错,这也是重写hashCode的原因。
讲解如下:
1.HashMap不允许key重复的含义:
请先明确:即使您未重写hashCode与equals,自定义类型作为HashMap的key,从代码上是完全被允许的。
HashMap中不允许key重复指的是逻辑重复,下图中的这种逻辑是不被允许的,但这种逻辑是存在的(不重写hashCode和equals就会导致如下情况,未重写两方法时两个属性相等的实例被视为不等的对象)
 
图 4-1
2.HashMap判别key是否重复的过程图:

图 4-2
只有重写了hashCode与equals,才能识别出重复的key,从而覆盖。
不重写hashCode与equals或只重写其中的一个,最终的结果都为key不等,无法识别出重复的key。
HashMap在设计时采用hashCode+equals方法为了提高性能,当hashCode不等时就没必要去调用equals来判断key是否重复了
3.源码(JDK1.7,HashMap的 put 方法)

五、验证:
1.原生hahsCde与equals验证:
import java.util.Objects;
/*
* 1.验证hashcode未重写哈希值为地址,即使属性完全相等的对象hshcode值也不同,而我们不需要这样的严格相等所以重写使得hashcode值与属性相关
* 2.验证equals为重写是比较的是内存地址,重写后比较的是属性,只有hsahcode相等两个对象才可能相等,equals相等的对象才彻底相等
*
* */
public class test {
public static void main(String[] args) {
//创建两个一模一样的对象
User user1 = new User(1,"小明");
User user2 = new User(1,"小明");
System.out.println("user1的哈希值:"+user1.hashCode());
System.out.println("user2的哈希值:"+user2.hashCode());
System.out.println("user1与user2的是否相等:"+user1.equals(user2));
}
}
class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
//hashCode与equals方法集成开发环境可自动生成,Intellij请用alt+insert
/*
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id == user.id &&
name.equals(user.name);
}
*/
/*@Override
public int hashCode() {
return Objects.hash(id, name);
}*/
}
结果如下:

此时两个属性完全相等的对象的哈希值不等,用equals方法比较结果为false.
2.重写euqals()的验证:
取消上面代码中重写的equals方法注释,执行代码。
结果如下:

3.逻辑冲突验证:
//放到上述main方法中
Map<User,Integer> map =new HashMap<User,Integer>();
User user1 = new User(1,"小明");
User user2 = new User(1,"小明");
map.put(user1,1);
map.put(user2,2);
System.out.println(map.get(user1));
System.out.println(map.get(user2));
结果如下:

相等的user对应着不同的int值,实际中有时不需要这样的逻辑。
4.解决逻辑冲突(重写hashCode与equals)验证:
请您将User中hashCode与equals方法注释取消再看结果。
结果如下:

此时不再允许key重复了,当再put相同的key值时发生覆盖。
5.您可自行重写hashCode、equals其中的一个来验证图4-2
六、其他
作者愚笨,如有问题请纠正。 |