jdk学习——HshMap

1. 基本数据结构

HashMap的底层数据结构是一个Hsah表,哈希表允许Java通过一个Hash函数将一个对象映射到一个数组的索引上,从而达到近似O(1)的访问和插入效率。

① 底层数组

那么Hash表的底层就是一个数组和一个哈希函数。

    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;
    }
    transient Node<K,V>[] table;

Node是HashMap中的基本节点,而table则是存储Hash表的底层数组

② 哈希函数(干扰函数)

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

其实在java中的哈希函数基本都是通过对象的hashCode函数实现的,Java并没有选用一些特别的hash算法。而是将这个实现能力几乎交给了用户对象自己实现各自相应的算法

上述的实现是Java对于对象的hashCode算法的一个干扰函数。其会将哈希二进制编码的高位扩散到哈希二进制编码低位,以使得哈希吗的高位也可能参与到哈希计算中,以增强哈希吗计算的随机性,以及减少相似的哈希码会产生的冲突。

举一个场景:如果哈希吗 2414 1001 和 5127 1001 两个编码(并非二进制)进行哈希运算,虽然两个编码的高位差异非常大,但是如果我们的哈希掩码是 0000 1111,那么其实哈希值的高位永远不可能参与到计算中。其实这样对于数字范围较大的数字,即是减少了哈希函数的随机性。

③ 掩码运算

在通常我们会认为HashMap的掩码运算就是HashMap的哈希函数——即很多人会认为,HashMap的哈希函数就是对hash值取余。其实我认为这个观点是错误的。取余只是一个掩码运算而并非一个哈希函数,在每一个哈希函数运算之后,得到一个索引只会,都会使用一个掩码对哈希值取余,受限于我们的内存永远是有限的内存,我们永远都希望能够尽量使用更少的内存,几乎所有的哈希函数计算完成之后都需要进行取余操作。

tab[(n - 1) & hash]

因此HashMap需要获取一个元素时,就需要像上述一样计算数组的下标,否则就一定会越界。

④ 常见的哈希函数——字符串

    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;
    }

以上代码是Java字符串的哈希函数,这个哈希函数的逻辑非常简单,计算方式是将字符串中的每一个char,乘以31,加上下一个char,再用结果乘以31,依次循环得到最后的哈希值。

这是Java中基于字符串实现的一个简单哈希计算的函数。

2. 操作详解

① 表容量计算函数

    static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值