美文网首页
Java基础->HashMap之hashCode

Java基础->HashMap之hashCode

作者: 杨0612 | 来源:发表于2020-12-03 11:46 被阅读0次

    (1)首先明确一点,hashCode函数返回类型是int类型,也就是32位;
    (2)生成hashCode原则,尽量让所有元素都参数运算,保证唯一性;
    (3)不同类型的key,生成算法不一样;

    Integer

    把value当成hashCode返回;

        public static int hashCode(int value) {
            return value;
        }
    
    Short、Byte

    直接把value转成int返回;

        public static int hashCode(byte value) {
            return (int)value;
        }
    
    Float

    因为涉及到小数,所以把value转成二进制,然后转成该二进制对应的Integer值返回(说实在话源码,我没怎么看懂,哈哈);

        public static int floatToIntBits(float value) {
            int result = floatToRawIntBits(value);
            // Check for NaN based on values of bit fields, maximum
            // exponent and nonzero significand.
            if ( ((result & FloatConsts.EXP_BIT_MASK) ==
                  FloatConsts.EXP_BIT_MASK) &&
                 (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
                result = 0x7fc00000;
            return result;
        }
    
    Long

    因为Long是64位,而且为了让所有元素都参与运算,将value无符号右移32位,异或原来二进制数(可以理解为高32位于低32位做运算),转成Integer返回,高低 32位都参数运算可以减少冲突,只要其中一位发生变化就能马上感知,

        public static int hashCode(long value) {
            return (int)(value ^ (value >>> 32));
        }
    
    Double

    因为Double涉及到小数,所以跟Float类型,先把value转成二进制,再转成对应的long,接下来就是Long类型的处理,无符号右移动32,做异或运算返回Integer值。

        public static int hashCode(double value) {
            long bits = doubleToLongBits(value);
            return (int)(bits ^ (bits >>> 32));
        }
    
    String

    以"abcd"为例,公式为:a31^3+b312+c*311+d31^0,a、b、c、d分別表示字母在ASCII值。其实这个计算公式在参考整数的计算,1234=1103+2*102+310^1+410^0。

    Tips:jdk采用31,因为31是奇素数,31*i会转换成位运算(i<<5)-i,运算比较快。
        public int hashCode() {
            int h = hash;
            final int len = length();
            if (h == 0 && len > 0) {
                for (int i = 0; i < len; i++) {
                    h = 31 * h + charAt(i);
                }
                hash = h;
            }
            return h;
        }
    
    自定义对象

    自定义对象的hashCode根据对象的内存地址生成的。

    Tips:即使计算过程中有溢出也没有关系,因为我们只需要结果;
    如果用与运算
        //与运算后的返回结果就是原始数据的低32位,这相当于高32位没有参与运算,
          所以与运算不合适。
        public void test() {
    /*            原始数据:11111111111111111111111111111111 10101010101010101010101010101010
    无符号右移32位,高位补0:00000000000000000000000000000000 11111111111111111111111111111111
                  原始数据:11111111111111111111111111111111 10101010101010101010101010101010
                与预算结果:00000000000000000000000000000000 10101010101010101010101010101010
    */
        }
    

    如果用或运算

        //或运算返回结果就是原始数据的高32位,这相当于低32位没有参与运算,
          所以或运算不合适。,
        public void test() {
    /*            原始数据:11111111111111111111111111111111 10101010101010101010101010101010
    无符号右移32位,高位补0:00000000000000000000000000000000 11111111111111111111111111111111
                  原始数据:11111111111111111111111111111111 10101010101010101010101010101010
                  或算结果:11111111111111111111111111111111 11111111111111111111111111111111
                  返回结果:                                 11111111111111111111111111111111
    */
        }
    

    相关文章

      网友评论

          本文标题:Java基础->HashMap之hashCode

          本文链接:https://www.haomeiwen.com/subject/wctpwktx.html