Java-HashCode

Java-HashCode

0x01 摘要

HashCode是jdk里面大量采用的一个方法,经常用来区分对象。本文谈谈hashCode在不同类的实现。

0x02 Object

public native int hashCode();

Object中定义的hashCode方法是一个native方法,他为不同Object返回了不同int型的hashCode。

Object.hashCode()基本原则有三:

  1. 在一个java程序生命周期内,不论对同一个对象调用此方法多少次都必须返回相同的hashcode
  2. Object.equals()方法相同的对象,hashCode必须相同
  3. java规范中并不要求equals方法不同的对象调用hashCode时就必须返回不同值,只不过设为不同值会提升性能,比如hashTable定位对象

0x03 Integer

public int hashCode() {
        return Integer.hashCode(value);
}

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

可见,Integer类中是直接返回对象的int值。

0x04 String

/** Cache the hash code for the string */
    private int hash; // hash初值为0
    
public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
}

注意:String类型的hash初始值为0
代码中将String的value转换为char数组,然后循环进行以下操作:
h = 31 * h + val[i]
val[i]就是该char值的Ascii码。那么这里就相当于是从字符串的左往右遍历,将每个字符的Ascii码 31*h,最后得到一个叠加出来的hash值。那么,如果字符串长度为0 则hashCode也会是0 。

这里选择31作为乘数的原因是因为3点:

  1. 31是较小的奇质数,使得结果不会太小导致冲突率高也不容易太大导致溢出
  2. 31 * i可以做这个等值优化:31h = 32*h - h = h<<5 - 1,这是移位运算速度极快
  3. 如果选择偶数,乘2相当于移位运算可能导致溢出,信息丢失

但要注意,jdk并不能保证不同String的hashCode不同,比如字符串"gdejicbegh"与字符串"hgebcijedg"具有相同的hashCode()返回值-801038016。

0x05 HashMap

0x06 WeakHashMap

final int hash(Object k) {
        int h = k.hashCode();
        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

这个算法和Jdk1.7中的HashMap相同,主要是尽量让所有k.hashCode()得到的bit的每一位变动都能体现在hash结果上(这种情况下只有原hashCode第3位高1位变化不会反应到结果中),让分布更均匀。最终使得落在HashMap的每个bucket中的元素数量更均匀,减少hash冲突。

0xFF 参考文档

科普:为什么 String hashCode 方法选择数字31作为乘子

Why does Java’s hashCode() in String use 31 as a multiplier?

HashMap 中hash table 定位算法

知乎关于HashMap hash方法讨论

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值