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常见问题

  1. == 和 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()?的主要内容,如果未能解决你的问题,请参考以下文章

java中为什么重写equals时必须重写hashCode方法?

重写了equals方法为何需要重写 hashCode

Java重写equals方法

java重写equals方法(重点讲解)

重写equals 方法的注意事项

重写hashcode和equals怎么重写