JDK8源码解析 -- HashMap(二)

唐宋源码清 2019-12-26

  在上一篇JDK8源码解析 -- HashMap(一)的博客中关于HashMap的重要知识点已经讲了差不多了,还有一些内容我会在今天这篇博客中说说,同时我也会把一些我不懂的问题抛出来,希望看到我这篇博客的大神帮忙解答困扰我的问题,让我明白一个所以然来。彼此互相进步,互相成长。HashMap从jdk7到jdk8版本改变大,1.新增加的节点在链表末尾进行添加  2.使用了红黑树。

  1. HashMap容量大小求值方法

// 返回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 >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

   (1)为什么这里需要 int n = cap - 1这样呢?

            首先我们要明白这个方法的作用是获取输入容量大小最近的2的幂次值。假设你传过来的参数cap是16的话,经过下面的运算得出来的值为32,而不是16。所以这里需要减去一。这样才能获此值最小的2幂次值。

    (2)这里左移之和为31=1+2+4+8+16,这里为什么是31呢?

             这里容量大小是int的类型,int的大小是32位,Integer的最大值是  2<sup>31</sup>-1。所以移动位数为31。还有如果 cap 不减一赋值给n的话,那么结果会超过此范围。 注意HashMap的最大容量为MAXIMUM_CAPACITY = 1 << 30;这里是30位,可能是因为如果这里是左移31的话,上面的计算值最坏的结果是1 <<< 32位,那么就超过了int的范围了,最高位是留给数字的正负符号位的。

  2.快速失败机制(fail-fast)

      HashMap只要结果发生了变化就会调用快速失败机制,除了iterator自己的 remove 方法,则迭代器将抛出ConcurrentModificationException。HashMap中有modCount字段记录结构改变次数,在进行迭代的时候判断此字段是否发生了变化。如果值不一样则会抛出异常。

  3. 红黑树特点

    (1)节点是红色或者黑色。

    (2)根节点是黑色。

    (3)红色节点的子节点是黑色。

    (4)每个叶子节点(NIL)是黑色。  

    (5)从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

注意:红色节点的子节点不能为红色,必须为黑色。黑色节点的子节点可以为红色也黑色。

抛出问题:

    1.HashMap的迭代器是怎么获取值的?例如 keySet()方法如下图,我也不明白怎么实现的。HashMap中也有ValueSet()等。如果有哪位大神知道其原理,请点拨一下我。:)

JDK8源码解析 -- HashMap(二)

相关推荐