为什么重写equals还要重写hashcode?

一个困扰很久的问题,在面试中也会遇到,最近通过看技术博客和看书查阅资料

,祝秋招顺利,如有不对之处,希望大家提出。

一、equals()方法

在jdk中Java的Object.equals()方法的底层是这样的

public boolean equals(Object object){
      return(this == obj);
}

可以看到这里直接用“==”来直接比较,“关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系”--Java编程思想

Java中的8种基本类型:数值型(byte、short、int、long、float、double)、字符型(char)、布尔型(boolean),对于8中基本类型的比较,变量存储的值,比较的话就是比较值本身,值相等就是true,不等就是false

public static void main(String[] args) {  
        int a=3;                                           
        int b=4;
        int c=3;
        System.out.println(a==b);   //false
        System.out.println(a==c);   //true
    }

对于非基本类型,也就是引用数据类型:类、接口、数组,由于变量存储的是地址,所以比较的该变量的地址,new出来的2个对象虽说值相等,但地址并不同

public static void main(String[] args) {
     String str1 = new String("aa");
     String str2 = new String("aa");
     System.out.println(str1 == str2); //false 
}

每个类型的比较都不一样,都会重写Object的equals()方法,下面我们可以看看String中的equals方法的怎么重写的

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

instanceof说明:如果 object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者 object 是 null,则返回 false。

二、hashCode()方法

该方法方法对象的哈希码值

在Java中,hashCode是jdk根据对象的地址或者字符串或者是数字算出来的int类型的数值。

常见的哈希码的算法有:

1:Object类的hashCode :返回对象的内存地址经过处理后的结构,由于每个对象的内存地址都不一样,所以哈希码也不一样。

2:String类的hashCode :根据String类包含的字符串的内容,根据一种特殊算法返回哈希码,只要字符串内容相同,返回的哈希码也相同。

3:Integer类 :返回的哈希码就是Integer对象里所包含的那个整数的数值,例如Integer i1=new Integer(100),i1.hashCode的值就是100

public static void main(String[] args) {
     List<Long> test1 = new ArrayList<Long>();
     test1.add(1L); 
     test1.add(2L);
     System.out.println(test1.hashCode()); //994 
     test1.set(0,2L); 
     System.out.println(test1.hashCode()); //1025
 }

三、为什么重写

先了解HashMap原理,HashMap存储数据时,是取key值的哈希值。内部实现通过Key对象的HashCode来计算得到"桶"的位置,这个“桶”里面可能会有多个对象(Entry对象,包含key对象和Value对象),因此它还会利用Key对象和里面对象的key调用equals逐一比较来找到目标对象。
  因此如果HashCode不同将会放进不同的两个桶中(除非HashMap内部的数组不能再扩大时,有可能会计算到相同的桶位置,不过出现情况应该比较少),因此myMap.get(b)不会得到你想要的目标对象。

因此Java重写equals方法必须重写hashcode方法!!

参考:https://www.jianshu.com/p/75d9c2c3d0c1

           https://blog.csdn.net/duxunlian8249/article/details/78092196

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值