理解HashMap中的Hash和tableSizeFor

在hashmap中是通过如下的算法来调整table的长度的,下面的算法的最终结果是构建一个2的幂次数。

    static final int MAXIMUM_CAPACITY = 1 << 30; //减一之后最长为30位1
    static final int tableSizeFor(int cap) {
        int n = cap - 1; //防止现在就是2的幂次,如果不减,经过下面的算法会把最高位后面的都置位1,再加1则相当于将当前的数值乘2
        n |= n >>> 1;  // 高位右移1位,保障高位和第二高位都为11
        n |= n >>> 2; //高两位右移2位,保障高4位都为1
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16; //保障最高的可达32位都为1
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

在HashMap中取一个key的hash值是如下操作的

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

原来的原来的hash值的高16位保持不变,低16位进行了异或操作,因为在hashmap存放数据的table中,放置数据的index的取值算法如下

(n - 1) & hash

n为table的长度,由于table的是2的幂次,减去1(即为table中可存放的最大的index),则数据存储的是全为1,最长为30位,再和hash与操作,则hash后面的长度会被取出来被均匀放到这个固定长度的数组中来,这样就容易造成只有hash的低位被取出来做index,很容易碰撞,如果先将hash的低位和高位异或处理,利用了hash的高位数据,也让低位的数据更加随机,减少碰撞的几率。

学习参考:HashMap源码注解 之 静态工具方法hash()、tableSizeFor()(四)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java集合:HashMap源码剖析 一、HashMap概述 二、HashMap的数据结构 三、HashMap源码...
    记住时光阅读 748评论 2 1
  • 一、HashMap概述 HashMap基于哈希表的Map接口的实现。此实现提供所有可选的映射操作,并允许使用nul...
    小陈阿飞阅读 655评论 0 2
  • 一、什么是交浅言深? 交浅言深:人际交往时,谈论的内容与人际关系发展的程度不相匹配,即关系低于谈论的内容。 自我表...
    algernon_阅读 967评论 0 0
  • 依稀记得,5岁的时候,家里来了一些亲戚。大家吃完晚饭,收拾好桌子,便开始闲聊。聊着聊着,不知道谁聊到了闹鬼的事,然...
    下一站就是黎明阅读 458评论 0 0
  • 支持原创,如需转载, 请注明出处@TEASON UIButton重复点击,重复触发,针对这些暴力调试,不能让方法无...
    TEASON阅读 3,625评论 1 26