文档章节

HahMap

o
 osc_1ee7cxmx
发布于 2018/08/06 16:25
字数 4762
阅读 0
收藏 0

精选30+云产品,助力企业轻松上云!>>>

HashMap的定义

public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable

1:HashMap中的字段及解释

static final int DEFAULT_INITIAL_CAPACITY = 16;   //默认初始容量,可以改变大小,但是必须为2的次方,2的n次方有利于Hash值的均分分布,
容量为什么一定是2的n次方:h & (length - 1) == h % length
static final int MAXIMUM_CAPACITY = 1073741824;  //最大容量2^30,  因为每次扩容要为以前的2倍。如果为2^31,扩容后为2^32,总容量为2^31+2^32>4G(32位操作系统内存). 
    static final float DEFAULT_LOAD_FACTOR = 0.75F;  //默认装载因子,当HashMap中装载比例达到DEFAULT_LOAD_FACTOR时,进行扩容。
    static final int TREEIFY_THRESHOLD = 8;          //将链表转化为红黑树的阈值,当每个桶中链表的长度大于8时,将链表转化为红黑树。从jdk1.8开始,HashMap底层数据结构为数组,链表,红黑树,Entry(Node)static final int UNTREEIFY_THRESHOLD = 6;        //由树转化为链表的阈值,当树的大小小于6时,转化为链表。
    static final int MIN_TREEIFY_CAPACITY = 64;      //当桶中的链表转化为红黑树时,Hashmap的最小容量
    transient HashMap.Node<K, V>[] table;            //节点(链表)数组(桶),插入的数据以链表(节点)的形式存储在数组中。
    transient Set<Entry<K, V>> entrySet;             //Entry键值对,每个节点中存储数据的形式。Node实现了Entry。  Node<u,v>.   hashMap数组中每个位置是链表,链表中每个节点是Entry形式的数据结构。
    transient int size;                              //记录Hash表的大小。                 
    transient int modCount;                          //记录Hash表别修改的次数,当HashMap迭代取出值时,remove,put,get操作都会改变修改次数modcount,并将其复制到迭代器的expectModCount属性中,当其它线程修改Map时,就会改变modCount。与期望的expectModCount不相同,抛出并发修改异常
    int threshold;                                   // 当前的阈值,阈值等于=容量*装载因子
    final float loadFactor;                          //装载当前的因子,当进行扩容后,装载因子会变化。

HashMap中的函数。

2:  hash  计算对象的Hash值

static final int hash(Object var0) {
        int var1;
        return var0 == null ? 0 : (var1 = var0.hashCode()) ^ var1 >>> 16;   //如果对象为null,那么hash值为0,
//如果不为空,hash值=var0的hashCode大小与var1无符号右移16的值做与运算。 }

3  putVal 向数组中添加值(节点)的函数

final V putVal(int var1, K var2, V var3, boolean var4, boolean var5) {
        HashMap.Node[] var6 = this.table;
        int var8;
        if (this.table == null || (var8 = var6.length) == 0) {
            var8 = (var6 = this.resize()).length;
        }

        Object var7;
        int var9;
        if ((var7 = var6[var9 = var8 - 1 & var1]) == null) {  //当数组中该位置为null时,直接将节点放入改位置
            var6[var9] = this.newNode(var1, var2, var3, (HashMap.Node)null);
        } else {
            Object var10;
            label79: {
                Object var11;
                if (((HashMap.Node)var7).hash == var1) {
                    var11 = ((HashMap.Node)var7).key;
                    if (((HashMap.Node)var7).key == var2 || var2 != null && var2.equals(var11)) {
                        var10 = var7;
                        break label79;
                    }
                }

                if (var7 instanceof HashMap.TreeNode) {
                    var10 = ((HashMap.TreeNode)var7).putTreeVal(this, var6, var1, var2, var3);
                } else {
                    int var12 = 0;

                    while(true) {
                        var10 = ((HashMap.Node)var7).next;
                        if (((HashMap.Node)var7).next == null) {
                            ((HashMap.Node)var7).next = this.newNode(var1, var2, var3, (HashMap.Node)null);
                            if (var12 >= 7) {   //如果长度大于7
                                this.treeifyBin(var6, var1);   //将链表变为树。
                            }
                            break;
                        }

                        if (((HashMap.Node)var10).hash == var1) {
                            var11 = ((HashMap.Node)var10).key;
                            if (((HashMap.Node)var10).key == var2 || var2 != null && var2.equals(var11)) {
                                break;
                            }
                        }

                        var7 = var10;
                        ++var12;
                    }
                }
            }

            if (var10 != null) {
                Object var13 = ((HashMap.Node)var10).value;
                if (!var4 || var13 == null) {
                    ((HashMap.Node)var10).value = var3;
                }

                this.afterNodeAccess((HashMap.Node)var10);
                return var13;
            }
        }

        ++this.modCount;
        if (++this.size > this.threshold) {
            this.resize();
        }

        this.afterNodeInsertion(var5);  //插入操作之后的其它操作。
        return null;
    }

4:tableSizeFor保证重新分配表之后的表大小为2的整数次幂

static final int tableSizeFor(int var0) {
        int var1 = var0 - 1;
        var1 |= var1 >>> 1;     //var1等于个var1与var1向右一位之后进行或运算。  var1=var1|var1>>>1 ;
        var1 |= var1 >>> 2;
        var1 |= var1 >>> 4;
        var1 |= var1 >>> 8;
        var1 |= var1 >>> 16; 
//中间过程的目的就是使n的二进制数的低位全部变为1,比如10,11变为11,100,101,110,111变为111;
return var1 < 0 ? 1 : (var1 >= 1073741824 ? 1073741824 : var1 + 1);
    }

5:putMapEntries ,迭代取出Map (变量var1)中的所有元素,使用putVal添加到table中.

final void putMapEntries(Map<? extends K, ? extends V> var1, boolean var2) {
        int var3 = var1.size();
        if (var3 > 0) {
            if (this.table == null) {
                float var4 = (float)var3 / this.loadFactor + 1.0F;
                int var5 = var4 < 1.07374182E9F ? (int)var4 : 1073741824;
                if (var5 > this.threshold) {  //如果超出阈值,就创建新表。
                    this.threshold = tableSizeFor(var5);  // 求出新表的大小,2的幂次。
                }
            } else if (var3 > this.threshold) {
                this.resize();
            }

            Iterator var8 = var1.entrySet().iterator();

            while(var8.hasNext()) {
                Entry var9 = (Entry)var8.next();
                Object var6 = var9.getKey();
                Object var7 = var9.getValue();
                this.putVal(hash(var6), var6, var7, false, var2);
            }
        }

    }

6:get函数 根据键取出元素,hash(var1) 计算hash值。

public V get(Object var1) {
        HashMap.Node var2;
        return (var2 = this.getNode(hash(var1), var1)) == null ? null : var2.value;  //获取节点的值
    }

7:getNode  获取hash值所在的节点

final HashMap.Node<K, V> getNode(int var1, Object var2) {
        HashMap.Node[] var3 = this.table;  //表数组
        HashMap.Node var4;
        int var6;
        if (this.table != null && (var6 = var3.length) > 0 && (var4 = var3[var6 - 1 & var1]) != null) {  //var3[var6-1&var1]  求出键在数组中的位置。
            Object var7;
            if (var4.hash == var1) {  //hash值相等。
                var7 = var4.key;
                if (var4.key == var2 || var2 != null && var2.equals(var7)) {  //通过键判断,equals
                    return var4;
                }
            }

            HashMap.Node var5 = var4.next;  //否则迭代,取出每一个节点,判断键是否相等。
            if (var4.next != null) {
                if (var4 instanceof HashMap.TreeNode) {
                    return ((HashMap.TreeNode)var4).getTreeNode(var1, var2);
                }

                do {
                    if (var5.hash == var1) {
                        var7 = var5.key;
                        if (var5.key == var2 || var2 != null && var2.equals(var7)) {  //当键相等的时候,返回找到的结果。
                            return var5;  
                        }
                    }
                } while((var5 = var5.next) != null);
            }
        }

        return null;
    }

8:containsKey判断键是否存在

public boolean containsKey(Object var1) {
        return this.getNode(hash(var1), var1) != null;  //根据键求节点,如果节点不为null,则键存在。
    }

9:resize重新调整表的大小,将原表的数据复制到新表中。原表置null

final HashMap.Node<K, V>[] resize() {
        HashMap.Node[] var1 = this.table;
        int var2 = var1 == null ? 0 : var1.length;
        int var3 = this.threshold;
        int var5 = 0;
        int var4;
        if (var2 > 0) {
            if (var2 >= 1073741824) {  //如果大于最大容量,那么返回原数组。
                this.threshold = 2147483647;
                return var1;
            }

            if ((var4 = var2 << 1) < 1073741824 && var2 >= 16) {  //扩大2倍
                var5 = var3 << 1;
            }
        } else if (var3 > 0) {
            var4 = var3;
        } else {
            var4 = 16;
            var5 = 12;
        }

        if (var5 == 0) {
            float var6 = (float)var4 * this.loadFactor;
            var5 = var4 < 1073741824 && var6 < 1.07374182E9F ? (int)var6 : 2147483647;
        }

        this.threshold = var5;
        HashMap.Node[] var14 = (HashMap.Node[])(new HashMap.Node[var4]); //新表
        this.table = var14;
        if (var1 != null) {
            for(int var7 = 0; var7 < var2; ++var7) {
                HashMap.Node var8;
                if ((var8 = var1[var7]) != null) {  //将原表中的节点一个一个取出
                    var1[var7] = null;
                    if (var8.next == null) {  //如果没有后继节点
                        var14[var8.hash & var4 - 1] = var8;  //直接将原表的节点复制到新表中。
                    } else if (var8 instanceof HashMap.TreeNode) {
                        ((HashMap.TreeNode)var8).split(this, var14, var7, var2);
                    } else {
                        HashMap.Node var9 = null;
                        HashMap.Node var10 = null;
                        HashMap.Node var11 = null;
                        HashMap.Node var12 = null;

                        HashMap.Node var13;
                        do {   //如果在原表中取出的节点右后继节点,那么迭代添加到新表中。
                            var13 = var8.next;    
                            if ((var8.hash & var2) == 0) {
                                if (var10 == null) {
                                    var9 = var8;
                                } else {
                                    var10.next = var8;
                                }

                                var10 = var8;
                            } else {
                                if (var12 == null) {
                                    var11 = var8;
                                } else {
                                    var12.next = var8;
                                }

                                var12 = var8;
                            }

                            var8 = var13;
                        } while(var13 != null);

                        if (var10 != null) {
                            var10.next = null;
                            var14[var7] = var9;
                        }

                        if (var12 != null) {
                            var12.next = null;
                            var14[var7 + var2] = var11;
                        }
                    }
                }
            }
        }

        return var14;
    }

10:  treeifyBin转化为树结构

final void treeifyBin(HashMap.Node<K, V>[] var1, int var2) {
        int var3;
        if (var1 != null && (var3 = var1.length) >= 64) {  //数组容量要大于64,才能转化
            int var4;
            HashMap.Node var5;
            if ((var5 = var1[var4 = var3 - 1 & var2]) != null) {
                HashMap.TreeNode var6 = null;
                HashMap.TreeNode var7 = null;

                do {
                    HashMap.TreeNode var8 = this.replacementTreeNode(var5, (HashMap.Node)null);
                    if (var7 == null) {
                        var6 = var8;
                    } else {
                        var8.prev = var7;
                        var7.next = var8;
                    }

                    var7 = var8;
                } while((var5 = var5.next) != null);

                if ((var1[var4] = var6) != null) {
                    var6.treeify(var1);  //递归
                }
            }
        } else {
            this.resize();
        }

    }

11: putAll 将Map中所有的数据添加到数组中。

public void putAll(Map<? extends K, ? extends V> var1) {
        this.putMapEntries(var1, true);  //使用putMapEntries函数。
    }

12:remove 移除某一个键值对

public V remove(Object var1) {
        HashMap.Node var2;
        return (var2 = this.removeNode(hash(var1), var1, (Object)null, false, true)) == null ? null : var2.value; //removeNode和getNode逻辑差不多,先找到键所对应的位置,将该节点移除。
    }

13: clear 清除,将数组中所有位置置为null。

public void clear() {
        ++this.modCount;
        HashMap.Node[] var1 = this.table;
        if (this.table != null && this.size > 0) {
            this.size = 0;

            for(int var2 = 0; var2 < var1.length; ++var2) {
                var1[var2] = null;
            }
        }

    }

14:containsValue 判断是否包含某一个值,  使用双层for循环,外层循环取出数组中每一个链表, 内层循环取出链表中每一个节点。

public boolean containsValue(Object var1) {
        HashMap.Node[] var2 = this.table;
        if (this.table != null && this.size > 0) {
            for(int var4 = 0; var4 < var2.length; ++var4) {
                for(HashMap.Node var5 = var2[var4]; var5 != null; var5 = var5.next) {
                    Object var3 = var5.value;
                    if (var5.value == var1 || var1 != null && var1.equals(var3)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

15:keySet  ,取出hashMap中的键集合

public Set<K> keySet() {
        Object var1 = this.keySet;  //集合,keySet继承自AbstractMap  里面的 transient Set<K> keySet;
if (var1 == null) {
            var1 = new HashMap.KeySet();
            this.keySet = (Set)var1;
        }

        return (Set)var1;
    }

16:  来自AbstractMap中的keySet().   

public Set<K> keySet() {
        Object var1 = this.keySet;
        if (var1 == null) {
            var1 = new AbstractSet<K>() {  //匿名内部类
                public Iterator<K> iterator() {
                    return new Iterator<K>() {
                        private Iterator<Entry<K, V>> i = AbstractMap.this.entrySet().iterator();

                        public boolean hasNext() {
                            return this.i.hasNext();
                        }

                        public K next() {
                            return ((Entry)this.i.next()).getKey();
                        }

                        public void remove() {
                            this.i.remove();
                        }
                    };
                }

                public int size() {
                    return AbstractMap.this.size();
                }

                public boolean isEmpty() {
                    return AbstractMap.this.isEmpty();
                }

                public void clear() {
                    AbstractMap.this.clear();
                }

                public boolean contains(Object var1) {
                    return AbstractMap.this.containsKey(var1);
                }
            };
            this.keySet = (Set)var1;
        }

        return (Set)var1;
    }

17:values返回值的集合,继承自abstractMap

public Collection<V> values() {
        Object var1 = this.values;
        if (var1 == null) {
            var1 = new HashMap.Values();
            this.values = (Collection)var1;
        }

        return (Collection)var1;
    }

18:  entrySet  求出所有Entry的集合。

public Set<Entry<K, V>> entrySet() {
        Set var1 = this.entrySet;
        return this.entrySet == null ? (this.entrySet = new HashMap.EntrySet()) : var1;
    }

19:getOrDefault,  通过键获取值,如果键为null,那么返回默认值

public V getOrDefault(Object var1, V var2) {
        HashMap.Node var3;
        return (var3 = this.getNode(hash(var1), var1)) == null ? var2 : var3.value;
    }

20:putIfAbsent  如果不存在就添加。  使用putVal函数。

public V putIfAbsent(K var1, V var2) {
        return this.putVal(hash(var1), var1, var2, true, true);
    }

21:不存在就添加,  值为一个函数式接口。可以在var2的位置直接放一个函数式即可。

public V computeIfAbsent(K var1, Function<? super K, ? extends V> var2) {
        if (var2 == null) {
            throw new NullPointerException();
        } else {
            int var3;
            HashMap.Node[] var4;
            int var6;
            int var8;
            HashMap.TreeNode var9;
            Object var10;
            label63: {
                var3 = hash(var1);
                var8 = 0;
                var9 = null;
                var10 = null;
                if (this.size <= this.threshold) {
                    var4 = this.table;
                    if (this.table != null && (var6 = var4.length) != 0) {
                        break label63;
                    }
                }

                var6 = (var4 = this.resize()).length;
            }

            HashMap.Node var5;
            int var7;
            Object var13;
            if ((var5 = var4[var7 = var6 - 1 & var3]) != null) {
                if (var5 instanceof HashMap.TreeNode) {
                    var10 = (var9 = (HashMap.TreeNode)var5).getTreeNode(var3, var1);
                } else {
                    HashMap.Node var11 = var5;

                    do {
                        if (var11.hash == var3) {
                            Object var12 = var11.key;
                            if (var11.key == var1 || var1 != null && var1.equals(var12)) {
                                var10 = var11;
                                break;
                            }
                        }

                        ++var8;
                    } while((var11 = var11.next) != null);
                }

                if (var10 != null) {
                    var13 = ((HashMap.Node)var10).value;
                    if (((HashMap.Node)var10).value != null) {
                        this.afterNodeAccess((HashMap.Node)var10);
                        return var13;
                    }
                }
            }

            var13 = var2.apply(var1);
            if (var13 == null) {
                return null;
            } else if (var10 != null) {
                ((HashMap.Node)var10).value = var13;
                this.afterNodeAccess((HashMap.Node)var10);
                return var13;
            } else {
                if (var9 != null) {
                    var9.putTreeVal(this, var4, var3, var1, var13);
                } else {
                    var4[var7] = this.newNode(var3, var1, var13, var5);
                    if (var8 >= 7) {
                        this.treeifyBin(var4, var3);
                    }
                }

                ++this.modCount;
                ++this.size;
                this.afterNodeInsertion(true);
                return var13;
            }
        }
    }

22:如果存在,就计算,然后添加计算的返回值。

public V computeIfPresent(K var1, BiFunction<? super K, ? super V, ? extends V> var2) {
        if (var2 == null) {
            throw new NullPointerException();
        } else {
            int var5 = hash(var1);
            HashMap.Node var3;
            if ((var3 = this.getNode(var5, var1)) != null) {  //获取存在的节点
                Object var4 = var3.value;
                if (var3.value != null) {
                    Object var6 = var2.apply(var1, var4);
                    if (var6 != null) {
                        var3.value = var6;
                        this.afterNodeAccess(var3);
                        return var6;
                    }

                    this.removeNode(var5, var1, (Object)null, false, true);
                }
            }

            return null;
        }
    }

23:clone克隆对象, 克隆为浅复制,仅仅复制一份对象的引用。  

public Object clone() {
        HashMap var1;
        try {
            var1 = (HashMap)super.clone();
        } catch (CloneNotSupportedException var3) {
            throw new InternalError(var3);
        }

        var1.reinitialize();
        var1.putMapEntries(this, false);
        return var1;
    }

 

 

 

 

 

 

 

transient HashMap.Node<K, V>[] table;

 

1:jdk1.8之前使用数组加链表的方式存储,装载因子过大时容易引起桶碰撞。

(1)JDK 1.8 以前 HashMap 的实现是 数组+链表,即使哈希函数取得再好,也很难达到元素百分百均匀分布。

(2)当 HashMap 中有大量的元素都存放到同一个桶中时,这个桶下有一条长长的链表,这个时候 HashMap 就相当于一个单链表,假如单链表有 n 个元素,遍历的时间复杂度就是 O(n),完全失去了它的优势。

(3)针对这种情况,JDK 1.8 中引入了红黑树(查找时间复杂度为 O(logn))来优化这个问题

static final int DEFAULT_INITIAL_CAPACITY = 16;      //初始容量
    static final int MAXIMUM_CAPACITY = 1073741824;      //2^30  最大容量,   容量为什么一定是2的n次方:h & (length - 1) == h % length
    static final float DEFAULT_LOAD_FACTOR = 0.75F;      //装载因子。   当map中装载这么多时,需要扩容。
static final int TREEIFY_THRESHOLD = 8;             //当链表的长度大于8时,存储方式转化为红黑树。

 每个键值对是以ENTRY<K,Y>  类型方式存储的。  ENTRY是一个接口,Node对齐进行实现,作为实际存储对象。链表形式存储复杂度为n

static class Node<K, V> implements Entry<K, V> {
        final int hash;
        final K key;
        V value;
        HashMap.Node<K, V> next;

        Node(int var1, K var2, V var3, HashMap.Node<K, V> var4) {
            this.hash = var1;
            this.key = var2;
            this.value = var3;
            this.next = var4;
        }

        public final K getKey() {
            return this.key;
        }

        public final V getValue() {
            return this.value;
        }

        public final String toString() {
            return this.key + "=" + this.value;
        }

        public final int hashCode() {
            return Objects.hashCode(this.key) ^ Objects.hashCode(this.value);   //用与进行计算hashCode值,和求余的结果相同
        }

        public final V setValue(V var1) {
            Object var2 = this.value;
            this.value = var1;
            return var2;
        }

        public final boolean equals(Object var1) {
            if (var1 == this) {
                return true;
            } else {
                if (var1 instanceof Entry) {
                    Entry var2 = (Entry)var1;
                    if (Objects.equals(this.key, var2.getKey()) && Objects.equals(this.value, var2.getValue())) {
                        return true;
                    }
                }

                return false;
            }
        }
    }

 

当装载因子大于8时,用红黑树进行存储,复杂度logn, 

static final class TreeNode<K, V> extends java.util.LinkedHashMap.Entry<K, V> {
        HashMap.TreeNode<K, V> parent;
        HashMap.TreeNode<K, V> left;
        HashMap.TreeNode<K, V> right;
        HashMap.TreeNode<K, V> prev;
        boolean red;

        TreeNode(int var1, K var2, V var3, HashMap.Node<K, V> var4) {
            super(var1, var2, var3, var4);
        }

        final HashMap.TreeNode<K, V> root() {
            HashMap.TreeNode var1 = this;

            while(true) {
                HashMap.TreeNode var2 = var1.parent;
                if (var1.parent == null) {
                    return var1;
                }

                var1 = var2;
            }
        }

        static <K, V> void moveRootToFront(HashMap.Node<K, V>[] var0, HashMap.TreeNode<K, V> var1) {
            int var2;
            if (var1 != null && var0 != null && (var2 = var0.length) > 0) {
                int var3 = var2 - 1 & var1.hash;
                HashMap.TreeNode var4 = (HashMap.TreeNode)var0[var3];
                if (var1 != var4) {
                    var0[var3] = var1;
                    HashMap.TreeNode var6 = var1.prev;
                    HashMap.Node var5 = var1.next;
                    if (var1.next != null) {
                        ((HashMap.TreeNode)var5).prev = var6;
                    }

                    if (var6 != null) {
                        var6.next = var5;
                    }

                    if (var4 != null) {
                        var4.prev = var1;
                    }

                    var1.next = var4;
                    var1.prev = null;
                }

                assert checkInvariants(var1);
            }

        }

        final HashMap.TreeNode<K, V> find(int var1, Object var2, Class<?> var3) {
            HashMap.TreeNode var4 = this;

            do {
                HashMap.TreeNode var8 = var4.left;
                HashMap.TreeNode var9 = var4.right;
                int var5 = var4.hash;
                if (var4.hash > var1) {
                    var4 = var8;
                } else if (var5 < var1) {
                    var4 = var9;
                } else {
                    Object var7 = var4.key;
                    if (var4.key == var2 || var2 != null && var2.equals(var7)) {
                        return var4;
                    }

                    if (var8 == null) {
                        var4 = var9;
                    } else if (var9 == null) {
                        var4 = var8;
                    } else {
                        int var6;
                        if ((var3 != null || (var3 = HashMap.comparableClassFor(var2)) != null) && (var6 = HashMap.compareComparables(var3, var2, var7)) != 0) {
                            var4 = var6 < 0 ? var8 : var9;
                        } else {
                            HashMap.TreeNode var10;
                            if ((var10 = var9.find(var1, var2, var3)) != null) {
                                return var10;
                            }

                            var4 = var8;
                        }
                    }
                }
            } while(var4 != null);

            return null;
        }

        final HashMap.TreeNode<K, V> getTreeNode(int var1, Object var2) {
            return (this.parent != null ? this.root() : this).find(var1, var2, (Class)null);
        }

        static int tieBreakOrder(Object var0, Object var1) {
            int var2;
            if (var0 == null || var1 == null || (var2 = var0.getClass().getName().compareTo(var1.getClass().getName())) == 0) {
                var2 = System.identityHashCode(var0) <= System.identityHashCode(var1) ? -1 : 1;
            }

            return var2;
        }

        final void treeify(HashMap.Node<K, V>[] var1) {
            HashMap.TreeNode var2 = null;

            HashMap.TreeNode var4;
            for(HashMap.TreeNode var3 = this; var3 != null; var3 = var4) {
                var4 = (HashMap.TreeNode)var3.next;
                var3.left = var3.right = null;
                if (var2 == null) {
                    var3.parent = null;
                    var3.red = false;
                    var2 = var3;
                } else {
                    Object var5 = var3.key;
                    int var6 = var3.hash;
                    Class var7 = null;
                    HashMap.TreeNode var8 = var2;

                    int var9;
                    HashMap.TreeNode var12;
                    do {
                        Object var11 = var8.key;
                        int var10 = var8.hash;
                        if (var8.hash > var6) {
                            var9 = -1;
                        } else if (var10 < var6) {
                            var9 = 1;
                        } else if (var7 == null && (var7 = HashMap.comparableClassFor(var5)) == null || (var9 = HashMap.compareComparables(var7, var5, var11)) == 0) {
                            var9 = tieBreakOrder(var5, var11);
                        }

                        var12 = var8;
                    } while((var8 = var9 <= 0 ? var8.left : var8.right) != null);

                    var3.parent = var12;
                    if (var9 <= 0) {
                        var12.left = var3;
                    } else {
                        var12.right = var3;
                    }

                    var2 = balanceInsertion(var2, var3);
                }
            }

            moveRootToFront(var1, var2);
        }

        final HashMap.Node<K, V> untreeify(HashMap<K, V> var1) {
            HashMap.Node var2 = null;
            HashMap.Node var3 = null;

            for(Object var4 = this; var4 != null; var4 = ((HashMap.Node)var4).next) {
                HashMap.Node var5 = var1.replacementNode((HashMap.Node)var4, (HashMap.Node)null);
                if (var3 == null) {
                    var2 = var5;
                } else {
                    var3.next = var5;
                }

                var3 = var5;
            }

            return var2;
        }

        final HashMap.TreeNode<K, V> putTreeVal(HashMap<K, V> var1, HashMap.Node<K, V>[] var2, int var3, K var4, V var5) {
            Class var6 = null;
            boolean var7 = false;
            HashMap.TreeNode var8 = this.parent != null ? this.root() : this;
            HashMap.TreeNode var9 = var8;

            HashMap.TreeNode var13;
            while(true) {
                int var11 = var9.hash;
                int var10;
                if (var9.hash > var3) {
                    var10 = -1;
                } else if (var11 < var3) {
                    var10 = 1;
                } else {
                    Object var12 = var9.key;
                    if (var9.key == var4 || var4 != null && var4.equals(var12)) {
                        return var9;
                    }

                    if (var6 == null && (var6 = HashMap.comparableClassFor(var4)) == null || (var10 = HashMap.compareComparables(var6, var4, var12)) == 0) {
                        if (!var7) {
                            var7 = true;
                            HashMap.TreeNode var14 = var9.left;
                            if (var9.left != null && (var13 = var14.find(var3, var4, var6)) != null) {
                                break;
                            }

                            var14 = var9.right;
                            if (var9.right != null && (var13 = var14.find(var3, var4, var6)) != null) {
                                break;
                            }
                        }

                        var10 = tieBreakOrder(var4, var12);
                    }
                }

                var13 = var9;
                if ((var9 = var10 <= 0 ? var9.left : var9.right) == null) {
                    HashMap.Node var16 = var13.next;
                    HashMap.TreeNode var15 = var1.newTreeNode(var3, var4, var5, var16);
                    if (var10 <= 0) {
                        var13.left = var15;
                    } else {
                        var13.right = var15;
                    }

                    var13.next = var15;
                    var15.parent = var15.prev = var13;
                    if (var16 != null) {
                        ((HashMap.TreeNode)var16).prev = var15;
                    }

                    moveRootToFront(var2, balanceInsertion(var8, var15));
                    return null;
                }
            }

            return var13;
        }

        final void removeTreeNode(HashMap<K, V> var1, HashMap.Node<K, V>[] var2, boolean var3) {
            int var4;
            if (var2 != null && (var4 = var2.length) != 0) {
                int var5 = var4 - 1 & this.hash;
                HashMap.TreeNode var6 = (HashMap.TreeNode)var2[var5];
                HashMap.TreeNode var7 = var6;
                HashMap.TreeNode var9 = (HashMap.TreeNode)this.next;
                HashMap.TreeNode var10 = this.prev;
                if (var10 == null) {
                    var6 = var9;
                    var2[var5] = var9;
                } else {
                    var10.next = var9;
                }

                if (var9 != null) {
                    var9.prev = var10;
                }

                if (var6 != null) {
                    if (var7.parent != null) {
                        var7 = var7.root();
                    }

                    if (var7 != null && var7.right != null) {
                        HashMap.TreeNode var8 = var7.left;
                        if (var7.left != null && var8.left != null) {
                            HashMap.TreeNode var12 = this.left;
                            HashMap.TreeNode var13 = this.right;
                            HashMap.TreeNode var14;
                            HashMap.TreeNode var15;
                            HashMap.TreeNode var16;
                            if (var12 != null && var13 != null) {
                                var15 = var13;

                                while(true) {
                                    var16 = var15.left;
                                    if (var15.left == null) {
                                        boolean var17 = var15.red;
                                        var15.red = this.red;
                                        this.red = var17;
                                        HashMap.TreeNode var18 = var15.right;
                                        HashMap.TreeNode var19 = this.parent;
                                        if (var15 == var13) {
                                            this.parent = var15;
                                            var15.right = this;
                                        } else {
                                            HashMap.TreeNode var20 = var15.parent;
                                            if ((this.parent = var20) != null) {
                                                if (var15 == var20.left) {
                                                    var20.left = this;
                                                } else {
                                                    var20.right = this;
                                                }
                                            }

                                            if ((var15.right = var13) != null) {
                                                var13.parent = var15;
                                            }
                                        }

                                        this.left = null;
                                        if ((this.right = var18) != null) {
                                            var18.parent = this;
                                        }

                                        if ((var15.left = var12) != null) {
                                            var12.parent = var15;
                                        }

                                        if ((var15.parent = var19) == null) {
                                            var7 = var15;
                                        } else if (this == var19.left) {
                                            var19.left = var15;
                                        } else {
                                            var19.right = var15;
                                        }

                                        if (var18 != null) {
                                            var14 = var18;
                                        } else {
                                            var14 = this;
                                        }
                                        break;
                                    }

                                    var15 = var16;
                                }
                            } else if (var12 != null) {
                                var14 = var12;
                            } else if (var13 != null) {
                                var14 = var13;
                            } else {
                                var14 = this;
                            }

                            if (var14 != this) {
                                var15 = var14.parent = this.parent;
                                if (var15 == null) {
                                    var7 = var14;
                                } else if (this == var15.left) {
                                    var15.left = var14;
                                } else {
                                    var15.right = var14;
                                }

                                this.left = this.right = this.parent = null;
                            }

                            var15 = this.red ? var7 : balanceDeletion(var7, var14);
                            if (var14 == this) {
                                var16 = this.parent;
                                this.parent = null;
                                if (var16 != null) {
                                    if (this == var16.left) {
                                        var16.left = null;
                                    } else if (this == var16.right) {
                                        var16.right = null;
                                    }
                                }
                            }

                            if (var3) {
                                moveRootToFront(var2, var15);
                            }

                            return;
                        }
                    }

                    var2[var5] = var6.untreeify(var1);
                }
            }
        }

        final void split(HashMap<K, V> var1, HashMap.Node<K, V>[] var2, int var3, int var4) {
            HashMap.TreeNode var6 = null;
            HashMap.TreeNode var7 = null;
            HashMap.TreeNode var8 = null;
            HashMap.TreeNode var9 = null;
            int var10 = 0;
            int var11 = 0;

            HashMap.TreeNode var13;
            for(HashMap.TreeNode var12 = this; var12 != null; var12 = var13) {
                var13 = (HashMap.TreeNode)var12.next;
                var12.next = null;
                if ((var12.hash & var4) == 0) {
                    if ((var12.prev = var7) == null) {
                        var6 = var12;
                    } else {
                        var7.next = var12;
                    }

                    var7 = var12;
                    ++var10;
                } else {
                    if ((var12.prev = var9) == null) {
                        var8 = var12;
                    } else {
                        var9.next = var12;
                    }

                    var9 = var12;
                    ++var11;
                }
            }

            if (var6 != null) {
                if (var10 <= 6) {
                    var2[var3] = var6.untreeify(var1);
                } else {
                    var2[var3] = var6;
                    if (var8 != null) {
                        var6.treeify(var2);
                    }
                }
            }

            if (var8 != null) {
                if (var11 <= 6) {
                    var2[var3 + var4] = var8.untreeify(var1);
                } else {
                    var2[var3 + var4] = var8;
                    if (var6 != null) {
                        var8.treeify(var2);
                    }
                }
            }

        }

        static <K, V> HashMap.TreeNode<K, V> rotateLeft(HashMap.TreeNode<K, V> var0, HashMap.TreeNode<K, V> var1) {
            if (var1 != null) {
                HashMap.TreeNode var2 = var1.right;
                if (var1.right != null) {
                    HashMap.TreeNode var4;
                    if ((var4 = var1.right = var2.left) != null) {
                        var4.parent = var1;
                    }

                    HashMap.TreeNode var3;
                    if ((var3 = var2.parent = var1.parent) == null) {
                        var0 = var2;
                        var2.red = false;
                    } else if (var3.left == var1) {
                        var3.left = var2;
                    } else {
                        var3.right = var2;
                    }

                    var2.left = var1;
                    var1.parent = var2;
                }
            }

            return var0;
        }

        static <K, V> HashMap.TreeNode<K, V> rotateRight(HashMap.TreeNode<K, V> var0, HashMap.TreeNode<K, V> var1) {
            if (var1 != null) {
                HashMap.TreeNode var2 = var1.left;
                if (var1.left != null) {
                    HashMap.TreeNode var4;
                    if ((var4 = var1.left = var2.right) != null) {
                        var4.parent = var1;
                    }

                    HashMap.TreeNode var3;
                    if ((var3 = var2.parent = var1.parent) == null) {
                        var0 = var2;
                        var2.red = false;
                    } else if (var3.right == var1) {
                        var3.right = var2;
                    } else {
                        var3.left = var2;
                    }

                    var2.right = var1;
                    var1.parent = var2;
                }
            }

            return var0;
        }

        static <K, V> HashMap.TreeNode<K, V> balanceInsertion(HashMap.TreeNode<K, V> var0, HashMap.TreeNode<K, V> var1) {
            var1.red = true;

            while(true) {
                HashMap.TreeNode var2 = var1.parent;
                if (var1.parent == null) {
                    var1.red = false;
                    return var1;
                }

                if (!var2.red) {
                    break;
                }

                HashMap.TreeNode var3 = var2.parent;
                if (var2.parent == null) {
                    break;
                }

                HashMap.TreeNode var4 = var3.left;
                if (var2 == var3.left) {
                    HashMap.TreeNode var5 = var3.right;
                    if (var3.right != null && var5.red) {
                        var5.red = false;
                        var2.red = false;
                        var3.red = true;
                        var1 = var3;
                    } else {
                        if (var1 == var2.right) {
                            var1 = var2;
                            var0 = rotateLeft(var0, var2);
                            var3 = (var2 = var2.parent) == null ? null : var2.parent;
                        }

                        if (var2 != null) {
                            var2.red = false;
                            if (var3 != null) {
                                var3.red = true;
                                var0 = rotateRight(var0, var3);
                            }
                        }
                    }
                } else if (var4 != null && var4.red) {
                    var4.red = false;
                    var2.red = false;
                    var3.red = true;
                    var1 = var3;
                } else {
                    if (var1 == var2.left) {
                        var1 = var2;
                        var0 = rotateRight(var0, var2);
                        var3 = (var2 = var2.parent) == null ? null : var2.parent;
                    }

                    if (var2 != null) {
                        var2.red = false;
                        if (var3 != null) {
                            var3.red = true;
                            var0 = rotateLeft(var0, var3);
                        }
                    }
                }
            }

            return var0;
        }

        static <K, V> HashMap.TreeNode<K, V> balanceDeletion(HashMap.TreeNode<K, V> var0, HashMap.TreeNode<K, V> var1) {
            while(var1 != null && var1 != var0) {
                HashMap.TreeNode var2 = var1.parent;
                if (var1.parent == null) {
                    var1.red = false;
                    return var1;
                }

                if (var1.red) {
                    var1.red = false;
                    return var0;
                }

                HashMap.TreeNode var3 = var2.left;
                HashMap.TreeNode var5;
                HashMap.TreeNode var6;
                if (var2.left == var1) {
                    HashMap.TreeNode var4 = var2.right;
                    if (var2.right != null && var4.red) {
                        var4.red = false;
                        var2.red = true;
                        var0 = rotateLeft(var0, var2);
                        var2 = var1.parent;
                        var4 = var1.parent == null ? null : var2.right;
                    }

                    if (var4 == null) {
                        var1 = var2;
                    } else {
                        var5 = var4.left;
                        var6 = var4.right;
                        if (var6 != null && var6.red || var5 != null && var5.red) {
                            if (var6 == null || !var6.red) {
                                if (var5 != null) {
                                    var5.red = false;
                                }

                                var4.red = true;
                                var0 = rotateRight(var0, var4);
                                var2 = var1.parent;
                                var4 = var1.parent == null ? null : var2.right;
                            }

                            if (var4 != null) {
                                var4.red = var2 == null ? false : var2.red;
                                var6 = var4.right;
                                if (var4.right != null) {
                                    var6.red = false;
                                }
                            }

                            if (var2 != null) {
                                var2.red = false;
                                var0 = rotateLeft(var0, var2);
                            }

                            var1 = var0;
                        } else {
                            var4.red = true;
                            var1 = var2;
                        }
                    }
                } else {
                    if (var3 != null && var3.red) {
                        var3.red = false;
                        var2.red = true;
                        var0 = rotateRight(var0, var2);
                        var2 = var1.parent;
                        var3 = var1.parent == null ? null : var2.left;
                    }

                    if (var3 == null) {
                        var1 = var2;
                    } else {
                        var5 = var3.left;
                        var6 = var3.right;
                        if ((var5 == null || !var5.red) && (var6 == null || !var6.red)) {
                            var3.red = true;
                            var1 = var2;
                        } else {
                            if (var5 == null || !var5.red) {
                                if (var6 != null) {
                                    var6.red = false;
                                }

                                var3.red = true;
                                var0 = rotateLeft(var0, var3);
                                var2 = var1.parent;
                                var3 = var1.parent == null ? null : var2.left;
                            }

                            if (var3 != null) {
                                var3.red = var2 == null ? false : var2.red;
                                var5 = var3.left;
                                if (var3.left != null) {
                                    var5.red = false;
                                }
                            }

                            if (var2 != null) {
                                var2.red = false;
                                var0 = rotateRight(var0, var2);
                            }

                            var1 = var0;
                        }
                    }
                }
            }

            return var0;
        }

        static <K, V> boolean checkInvariants(HashMap.TreeNode<K, V> var0) {
            HashMap.TreeNode var1 = var0.parent;
            HashMap.TreeNode var2 = var0.left;
            HashMap.TreeNode var3 = var0.right;
            HashMap.TreeNode var4 = var0.prev;
            HashMap.TreeNode var5 = (HashMap.TreeNode)var0.next;
            if (var4 != null && var4.next != var0) {
                return false;
            } else if (var5 != null && var5.prev != var0) {
                return false;
            } else if (var1 != null && var0 != var1.left && var0 != var1.right) {
                return false;
            } else if (var2 != null && (var2.parent != var0 || var2.hash > var0.hash)) {
                return false;
            } else if (var3 == null || var3.parent == var0 && var3.hash >= var0.hash) {
                if (var0.red && var2 != null && var2.red && var3 != null && var3.red) {
                    return false;
                } else if (var2 != null && !checkInvariants(var2)) {
                    return false;
                } else {
                    return var3 == null || checkInvariants(var3);
                }
            } else {
                return false;
            }
        }
    }

 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。

暂无文章

2020-07-03:有1亿个数字,其中有2个是重复的,快速找到它,时间和空间要最优

福哥答案2020-07-03: 1.双重遍历。 时间复杂度是O(N^2)。 2.排序。 采用外部排序。时间复杂度是O(NlogN)。 3.遍历加哈希存储。 空间换时间,时间复杂度是O(N),空间复杂度是O(N)。这种方法适...

osc_ix000whh
15分钟前
9
0
O2OA开源免费开发平台:在O2门户页面中使用React(三)

在前面的章节中,我们介绍了两种在O2OA中使用React开发应用的方式,已经可以满足绝大多数的情况了。如果您考虑完全脱离O2的web服务器,自己搭建web服务器,那就请阅读本章。   我们还是使用...

O2OA企业信息化平台
15分钟前
18
0
harbor 2.0 搭建docker私有仓库

harbor Harbor 是一个CNCF基金会托管的开源的可信的云原生docker registry项目,可以用于存储、签名、扫描镜像内容,Harbor 通过添加一些常用的功能如安全性、身份权限管理等来扩展 docker r...

osc_l7zl78wt
17分钟前
17
0
Java并发编程(06):Lock机制下API用法详解

本文源码:GitHub·点这里 || GitEE·点这里 一、Lock体系结构 1、基础接口简介 Lock加锁相关结构中涉及两个使用广泛的基础API:ReentrantLock类和Condition接口,基本关系如下: Lock接口 ...

osc_kiub62pt
18分钟前
22
0
DNS存在的问题

1、域名缓存问题 本地做一个缓存,直接返回缓存数据。可能会导致全局负载均衡失败,因为上次进行的缓存,不一定是这次离客户最近的地方,可能会绕远路。 2、域名转发问题 如果是A运营商将解析...

mind-blowing
19分钟前
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部