JAVA8 中HASHMAP 分析

本文详细剖析了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/silver9886@126/blog/static/359718622017818916446/
http://blog.163.com/silver9886@126/blog/static/35971862201782111627311/
上文章还有一些问题 于是有第二篇
http://blog.163.com/silver9886@126/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.youkuaiyun.com/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;
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值