JAVA8 中HASHMAP 分析

JAVA8 中HASHMAP 分析 

相关知识点 : 

红黑树特点

1. 每个节点是红色或黑色

2. 根是黑色

3. 叶节点(null)是黑色的

4. 红色的节点的两个子结点均为黑色

5. 对于每个节点,从该节点到其所有后代的简单路径上,均包含相同数目的黑色节点(我们把到叶节点的黑色节点数称为黑高)

hashmap 的容量是Integer.MAX+1 / 2

hashmap 中节点的hash 是其中 hash 是无符号右移16位按位异或 hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

TreeNode 节点中有2中数据结构 1, 继承自Node的单链结构next + 自身维持的prev  2, 自身实现的红黑树结构

TreeNode 中的数据结构

     
TreeNode<K,V> parent;  // red-black tree links

        TreeNode<K,V> left;

        TreeNode<K,V> right;

        TreeNode<K,V> prev;    // needed to unlink next upon deletion [ 删除后需要取消链接 ]

        boolean red;           // 颜色属性

TreeNode 

putVal 返回的是前一节点且可能为空, 此时 p = tab[i = (n – 1) & hash] p 不会为空

Spliterator

(splitable iterator可分割迭代器)接口是Java为了并行遍历数据源中的元素而设计的迭代器,

这个可以类比最早Java提供的顺序遍历迭代器Iterator,但一个是顺序遍历,一个是并行遍历

|- boolean tryAdvance(Consumer<? super T> action);顺序处理每个元素,类似Iterator,如果还有元素要处理,则返回true,否则返回false

|- Spliterator<T> trySplit();———————该方法会把当前元素划分一部分出去创建一个新的Spliterator作为返回,

|
  两个Spliterator变会并行执行,如果元素个数小到无法划分则返回null                          

|- long estimateSize();—————————该方法用于估算还剩下多少个元素需要遍历,影响代码执行线程数                           

|- int characteristics();————————-对流的计算有优化作用, 可能对计算结果会产生影响 

|-
  return ORDERED | SIZED | SUBSIZED | NONNULL | IMMUTABLE |DISTINCT;   

|- forEachRemaining –>  do { } while (tryAdvance(action));  

|- getComparator()——————————–对sorted的流,给出比较器               

引用大神的分析  后面再写文章分析

参考 http://blog.163.com/
[email protected]/blog/static/359718622017818916446/

http://blog.163.com/
[email protected]/blog/static/35971862201782111627311/

上文章还有一些问题 于是有第二篇

http://blog.163.com/
[email protected]/blog/static/35971862201782111627311/

hashmap 最大容量  1 << 30 (Integer的最大值+1 ) / 2 

当hashmap的最大值达到 1<<30时 会将 threshold 设置成  threshold = Integer.MAX_VALUE; 然后 return

// The next size value at which to resize (capacity * load factor).

hashmap 类结构  extends AbstractMap implements Cloneable

内部类结构 :

Node 

KeySet

Values

EntrySet

HashIterator 

KeyIterator

ValueIterator

EntryIterator

HashMapSpliterator

KeySpliterator

ValueSpliterator

EntrySpliterator

TreeNode  重点(红黑树的实现)

方法 :

构造方法4个 默认,initialCapacity, initialCapacity + loadFactor, Map

关键方法

putVal resize remove

关键数据结构

Node 实现 Map.Entry  TreeNode 继承于 Node 都继承 Map.Entry

当hash 冲突达到一定条件的时候会转成链表 当链表的长度 >= 7 则当前链表转成红黑树

–> 关键代码

    final void treeifyBin(Node<K,V>[] tab, int hash) {
//

        int n, index; Node<K,V> e;
//

        if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
//

            resize();
//如果桶(slot)的个数即是容量没达到64时 则resize()

        else if ((e = tab[index = (n – 1) & hash]) != null) {
//

            TreeNode<K,V> hd = null, tl = null;
//

            do {
//

                TreeNode<K,V> p = replacementTreeNode(e, null);     
//将每个node转成TreeNode
       

                if (tl == null)
//

                    hd = p;
//

                else {
//

                    p.prev = tl;
//

                    tl.next = p;
//

                }
//

                tl = p;
//

            } while ((e = e.next) != null);
//此while 循环生成一个TreeNode的双向链表

            if ((tab[index] = hd) != null)
//

                hd.treeify(tab);—————————————-//将节点转成红黑树

        }
//

    }
//

然后就是红黑树的实现 (可参考此文章)

http://blog.csdn.net/sun_tttt/article/details/65445754

resize 关键代码

if ((e = oldTab[j]) != null) {

        oldTab[j] = null;

        if (e.next == null)

            newTab[e.hash & (newCap – 1)] = e;

        else if (e instanceof TreeNode)

            ((TreeNode<K,V>)e).split(this, newTab, j, oldCap); //如果是红黑树则split

        else { // preserve order

            Node<K,V> loHead = null, loTail = null;

            Node<K,V> hiHead = null, hiTail = null;

            Node<K,V> next;

            do {

                next = e.next;

                if ((e.hash & oldCap) == 0) {   
//将原来链表中链接拆分成低位 和 高位 2条链  

               
//其中hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

                    if (loTail == null)

                        loHead = e;

                    else

                        loTail.next = e;

                    loTail = e;

                }

                else {

                    if (hiTail == null)

                        hiHead = e;

                    else

                        hiTail.next = e;

                    hiTail = e;

                }

            } while ((e = next) != null);

            if (loTail != null) {

                loTail.next = null;

                newTab[j] = loHead;

            }

            if (hiTail != null) {

                hiTail.next = null;

                newTab[j + oldCap] = hiHead;

            }

        }

    }

点赞