美文网首页
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