Java中为什么重写equals()也需要重写hashCode()?
Posted 武帅祺的官方网站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中为什么重写equals()也需要重写hashCode()?相关的知识,希望对你有一定的参考价值。
所有类默认继承Object类 先看一下Object源码
package java.lang;
public class Object
//默认调用本地的hashcode()方法 根据内存地址生成hash值 避免不了哈希冲突
public native int hashCode();
//默认调用的equals方法比较的是\'==\'比较
//基本类型比较的是两者的值是否相同 而引用类型比较两者的是引用地址(对象)是否相同
public boolean equals(Object obj)
return (this == obj);
结论
- equals()返回结果为true hashCode()一定相同
- \'==\'结果为true hashCode()一定相同
- \'==\'结果为false hashCode()有可能相同(哈希冲突)
hashCode()重写规范就是保证equals()相同的两个对象拥有相同的哈希值
回到刚刚哪个问题 为什么重写equals还要重写hashCode()?
public class per
private String name;
private int age;
public per(String name, int age)
this.name = name;
this.age = age;
public boolean equals(Object o)
if (this==o)return true;
if (o==null||o.getClass()!=this.getClass())return false;
per o1 = (per) o;
return o1.name==name&&o1.name!=null&&o1.name.equals(this.name)&&age=o1.age;
public int hashCode()
return Objects.hash(name,age);
/*
这是Object类中的规范如果不同时重写将会导致很多类库出现业务不一致!
例如HashMap无法保证key值\'唯一性\'
下面测试代码p1和p2虽然地址不同 但是业务上看内容是相同的
所以应该只用一个key表示 但是不重写将无法正确插入!
*/
class Example
public static void main(String[] args)
per p1 = new per("张三", 18);
per p2 = new per("张三", 18);
HashMap<per,Integer> map = new HashMap<>();
map.put(p1,1);
map.put(p2,2); //具体原理可以看put(k,v)源码!
JAVA常见问题
- == 和 equals()
- 两个对象使用==,比较的是对象引用;
- 如果要比较内容相等,一般使用equals(但不包括primitive类型);
- equals默认是判断两个对象是否==,所以默认比较两个对象的引用;但是JAVA有些类重写了equals方法,实现判断内容是否也相等,如String, Date, Double,Integer,所以自定义类要实现equals,需要重写equals方法,同时有必要重写hashcode方法(既然要两个对象equals,那严格意义上hashcode也是一致的,否则在如HashMap,HashTable类似的集合存储以对象为key会有问题,因为是否重复是以对象key的hashcode值来判断重复);
- 所以说,两个对象equals,则hashcode相等;但是hashcode相同的两个对象,不一定equals。
- 注意:如果定义String str1="Test"; String str2 = "Test", str1 == str2 返回是true。
- Map中以hash查找之所以高效(而不是通过遍历所有元素):首先将Map分区,然后将hashcode按某种规则分区存储,查找时只要先找到对应的区,最后在那个区进行遍历。
以上是关于Java中为什么重写equals()也需要重写hashCode()?的主要内容,如果未能解决你的问题,请参考以下文章