小言_互联网的博客

Java基础--理解hashCode

397人阅读  评论(0)

1.hashCode

什么是hashCode?

根据jdkapi文档,可以很明确的得知hashCode的特点:

    1. 在一次运行期间,同一对象的equal比较信息没有被修改hashCode一定相同
    1. 如果对象的equals方法相同,那么hashCode一定相同
    1. 可以存在equals不等,但是hashCode相等的数据

接下来看看hashCode方法的定义:

因为Object是Java所有类的父类,所以,Java所有类的默认的hashCode的方法就是Object的hashCode方法。Object的hashCode方法是一个native方法,即用平台相关语言实现的,由Java调用的方法。Object的hashCode方法是返回其内存地址经过计算后的数据。
hashCode返回的是一个int型的值。

2.equals

equals方法是Java中判断一个对象是否相等的重要的方法。

equals方法需要满足一下特性:

  • 自反性:非空X,X对自己的equals一定是true
  • 对称性:非空X,Y;如果X.equals(Y)是true,那么,Y.equaks(X)一定是true
  • 传递性:非空X,Y,Z:如果X.equals(Y),Y.equals(Z),那么X.equals(Z)
  • 一致性:非空X,Y:如果X.equals(Y),那么在一次运行中,任何时候,任何情况下都满足(equals的属性未修改)
  • null:非空X:X.equals(null)一定false

持此之外,equals方法和==通常意义不同。
equals可以自定义比较的属性
==如果是基本类型,就是比较其值
如果==不是基本类型,而是引用类型,那么比较的就是引用地址了。

3. equals & hashCode

一般情况下,普遍的通识中,会默认保证:
如果equals是true,那么hashCode相等。
这一原则。

为什么?

1.hashCode的设计目的是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。
哈希表存储数据会将hashCode相同的数据放到同一个哈希桶里。
所以,如果hashCode不相等,但是equals却相等,在使用哈希表等数据结构时,就无法提升其性能了。

2.不仅仅是性能问题,hashCode在许多的数据结构中都有涉及,所以,尽可能保证这一原则非常重要。

4.例子

import java.util.HashSet;
import java.util.Set;

/**
 * @author jiayq
 * @Date 2020-04-21
 */
public class HashMain {

    private int myHash;

    public HashMain(){
        this.myHash = hashCode();
    }

    public static void main(String[] args){
        HashMain hashMain = new HashMain();
        //输出hashCode(hashCode一般以16进制进行展示或者运算)
        System.out.println(Integer.toHexString(hashMain.hashCode()));
        //调用Object的toString方法
        System.out.println(hashMain);
        System.out.println(27 & 0b1110);
        // 27 = 0b 0001 1011 & 0b 0000 1110 => 0b 0000 1010
        System.out.println(27 ^ 0xE);
        // 27 = 0b 0001 1011 ^ 14 => 0b 0000 1110 => 0001 0101 = 21
        HashMain hashMain1 = hashMain;
        //比较引用
        System.out.println(hashMain == hashMain1);
        //比较equals
        System.out.println(hashMain.equals(hashMain1));
        //设置属性
        hashMain.myHash = 1;
        //创建不同的对象
        hashMain1 = new HashMain();
        //设置属性
        hashMain1.myHash = 1;
        //比较equals
        System.out.println(hashMain.equals(hashMain1));
        //输出hashCode
        System.out.println(hashMain.hashCode());
        System.out.println(hashMain1.hashCode());
        //调用Object的toString输出
        System.out.println(hashMain);
        System.out.println(hashMain1);
        //Set不允许重复数据,其重复的标准是equals方法
        //如果hashCode相同,那么会将数据放到同一个哈希桶里
        //如果equals相同,那么不会进行存储,注意,在判断equals之前会判断hashCode相等
        //也就是说,如果两个对象的hashCode不同,其equals相同,那么Set也会将这两个对象当做不同的数据进行存储
        //反之,如果两个对象的hashCode相同,那么会继续判断equals
        //1.hashCode不同,equals相同
        Set<HashMain> set = new HashSet<>();
        set.add(hashMain);
        set.add(hashMain1);
        System.out.println(set);
        set.clear();
        //2.hashCode相同,equals不同
        hashMain1.myHash = 2;
        set.add(hashMain);
        set.add(hashMain1);
        System.out.println(set);
    }


    /**
     * 重写了子类的hashCode的方法
     * @return
     */
    @Override
    public int hashCode() {
        // 0b1111 = 1+2+4+8 = 15
        // value & 0b1111 -> [0,15]
        // value & (ob1111 - 1) -> [0,14] => 0b 1110 & value => 高 3 位
        //调用Object的hashCode方法,将返回的结果取低4位(0~15),类似将数值 >>> 60
        //同时 value % 16 等价于 value & 0b1111 <=> value &0xF
        //场景1.hashCode不同,equals相同
        return super.hashCode() & 0b1111;
        //2.hashCode相同,equals不同
//        return this.getClass().getName().hashCode();
    }


    /**
     * 重写了子类的equals方法
     * @param obj
     * @return
     */
    @Override
    public boolean equals(Object obj) {
        //类型相同
        if (obj instanceof HashMain){
            HashMain main = (HashMain) obj;
            //属性相同
            return this.myHash == main.myHash;
        }
        return false;
    }

}



5. 总结

hashCode的目的是提升哈希表的性能。
哈希表在存储的时候会先调用hashCode进行比较,然后使用equals进行比较
为了更好的使用哈希表,需要保证equals相等,hashCode一定相等
默认的hashCode是内存地址进行运算
hashCode将对象的部分差异集中到了int数据中
hashCode一般可以实现对象比较的先行比较


转载:https://blog.csdn.net/a18792721831/article/details/106004311
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场