HashMap在JDK1.7和JDK1.8的改动

Integer.MAX_VALUE = 2 ^ 31 - 1;

HashMap table 的最大大小 1 << 30 = 2 ^ 30

HashMap 查找的时间复杂度 O(1) + O(n) (before JDK 1.7) | O(1) + O(logN) (after JDK 1.8)

JDK 1.7 和 1.8 的区别

  1. JDK1.7用的是头插法,而JDK1.8及之后使用的都是尾插法,那么他们为什么要这样做呢?因为JDK1.7是用单链表进行的纵向延伸,当采用头插法时会容易出现逆序且环形链表死循环问题 (在并发环境中进行扩容时)。但是在JDK1.8之后是因为加入了红黑树使用尾插法,能够避免出现逆序且链表死循环的问题。
  2. 扩容后数据存储位置的计算方式也不一样:1. 在 JDK1.7 的时候是直接用 hash 值和需要扩容的二进制数进行&(这里就是为什么扩容的时候为啥一定必须是2的多少次幂的原因所在,因为如果只有2的n次幂的情况时最后一位二进制数才一定是1,这样能最大程度减少 hash 碰撞) (hash值 & length-1)

Key 的 Hash 策略

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

/*	
	这里 HashMap 的最大容量只能到 Integer.MAX_VALUE 的一半。原因是 HashMap 的容量必须是 2 的整数次幂,其二进制表示必须为 某位为1,其余所有位均为0。这个最大值是 1 << 30。
	
	这个方法接收的参数是 KEY 的 hashCode, 由于在计算位置时使用了 原理上与取余一样的位操作 , 
	table 长度 n 为 2 的整数次幂,并且 table 的最大值为 1 << 30,所以在进行计算 hash 时只会用到 int 的低 16 位,设计者认为如果只取低 16 位很容易产生 Hash 碰撞,所以也将 高 16 位 右移过来参与了计算。
*/

HashMap 中的一些常量

    /**
     * The load factor used when none specified in constructor.
     * 默认的装填因子
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * The default initial capacity - MUST be a power of two.
     * 默认的容量
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    /**
     * 最大容量
     * MUST be a power of two <= 1<<30.
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * 容量大于 8 转为红黑树
     */
    static final int TREEIFY_THRESHOLD =
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值