HashMap解析

本文详细解析了HashMap的内部实现,包括其解决的效率问题、数组大小的确定、hash计算方法以及元素在数组中的定位。讨论了为何数组大小选择2的n次方、hash计算中右移16位的原因以及如何通过(n-1)&hash确定位置。此外,还介绍了HashMap的扩容策略,包括何时扩容、扩容的具体操作以及为何采用特定的扩容方式。最后,提到了链表转红黑树的优化,以避免链表过长导致的性能下降。
摘要由CSDN通过智能技术生成

开门见山,直接开始

HashMap解决了什么问题?

HashMap解决了插入与查找的效率问题,内部实现是通过数组和链表组合实现
在这里插入图片描述

HashMap如何确定数组大小

结论,根据传入的size大小,计算下一个最接近传入size大小的2的n次方(可能是size本身),例如,传入size为15,真实size为2的四次方16,代码如下:

 /**
     * Returns a power of two size for the given target capacity.
     */
    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 >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

代码流程:
通过减1后进行右移操作,可以将数据的最高位1之后数据全部置1,对结果进行边界判断,如非负数或者超过int大值,则+1就可获取最接近(包括本身)输入size的下一个2的n次方

几步右移操作为了将最高位1之后的所有位数置为1
例如输入size 为15 ,减一操作后为n为14,二进制数据为0000 0000 0000 1110
右移1位或上本身,.得出n=0000 0000 0000 1111 ,实际上已经得出结果,后面操作不影响,其他32位数字类似

疑问一: 为什么要-1?

结论: 因为tableSizeFor是为了计算出下一个2的n次方数字,结果大于等于当前传入值,比如传入8,如不减一操作最后计算结果为16,显然不行

疑问二:为什么size要2的n次方:?
结论:一是为了减少hash碰撞,二是为了更高效的计算key在数组中的位置

疑问二;为什么要选择这种方式计算2的n次方
结论:cpu计算中,加减乘除的效率没有移位操作快,移位操作可以获得最高效率

HashMap 如何计算hash?

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

代码很简单,直接对key的hashcode和key的hashcode右移16位进行异或运算

疑问一: 为什么要右移16位?

结论:为了使hashcode的高位16位也能参与hash运算,增大散列程度,减少hash冲突

HashMap如何确定元素在数组中的位置

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                  boolean evict) {
   
       Node<K,V
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值