关于HashMap的扩容机制和及其算法的一些思考

247 阅读3分钟

关于HashMap的扩容机制和及其算法的一些思考

一、前言

本文为HashMap源码记录篇幅之一,引用了部分基础知识的URL,侵删

mail:dustfree2018@gmail.com

二 、基础

1 位运算

  • "<<<" :无符号左移动三位,

    8-> 0000 1000 左移动三位 0100 0000=2^6= 32

  • ">>>": 无符号右移动三位

    8-> 0000 1000 右移动三位 0000 0001 =2^0=1

  • "|=" : 或等于

    有1则为1 ,反之为0。

    例: 0000 1000

    右移三位得 0000 0001

    = 0000 1001=9

三 解析

/**
 * The maximum capacity, used if a higher value is implicitly specified
 * by either of the constructors with arguments.
 最大容量,如果隐式指定更高的值,则使用该容量
 * MUST be a power of two <= 1<<30.
 * 必须是两个<= 1 << 30的幂。
 */
static final int MAXIMUM_CAPACITY = 1 << 30;
static int tableSizeFor(int cap) {
        int n = cap - 1;
        //>>>二进制无符号右移
        //|= n 的二进制 有1则为1, 否则为0
        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. cap<=0000 0100 假设为4,减1后为 0000 0011

     n |= n >>> 1;
    
    1. 3>>1=0000 0001=1
    2. 3|=1 ->0000 0011|=0000 0001=0000 0011=3

    右移大于1位时,则右移后的数字为0。与原值进行|= 运算无意义,因此不做详解。

    结论,等于cap<=4即cap<=0000 0100 cap不做变更,为原值。

  2. cap>=0000 0100 假设cap=35 减1后为34 -> 0010 0010

    n |= n >>> 1;
    
  1. n=cap-1=34
  2. n -> 0010 0010
  3. n>>>1= 0001 0001
  4. 0010 0010 |= 0001 0001 得出 0011 0011 ->32+16+2+1=41=n
 n |= n >>> 2;
  1. 0011 0011>>>2 -> 0000 1100
  2. 0011 0011 |= 0000 1100=0011 1111
  3. n= 63
n |= n >>> 4;
  1. 0011 1111 >>>4 得到 0000 1111
  2. 0011 1111 |= 0000 1111 得到 0011 1111
  3. n=63

………………

右移大于8位,右移后的数值为0 ,进行|= 运算为左侧(n)值,此时无意义,更大数字可以进行尝试,结论一致。

(n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;

n+1=64

五 结论

  • 等于cap<=4即cap<=0000 0100 cap不做变更,为原值。

  • cap大于等于4 二进制为0000 0100 ,向上取值,其二进制数最终结果为其去除补位0后,最高位为1的位置为起始点,后续数值转换为1。比如:传入cap=5 n=cap-1=4->0100 右移一位得 0010 |= 0110 然后

    1. n=cap-1=4 0100
    2. n>>>1. 0010
    3. n|=0010 0110
    4. n>>>2 0001
    5. n|=0001 0111
    6. 得出结果,7
    7. cap=n+1=8