zoukankan      html  css  js  c++  java
  • HashMap 1.8 源码

    public class HashSet<E> {//1.8版本
        private transient HashMap<E,Object> map;
        //1-1. 创建一个HashMap对象,并且调用无参构造函数
        public HashSet() {
            map = new HashMap<>();
        }
        
        public HashSet(int initialCapacity, float loadFactor) {
            map = new HashMap<>(initialCapacity, loadFactor);
        }
    
        public HashSet(int initialCapacity) {
            map = new HashMap<>(initialCapacity);
        }
        
        //2-1. 添加第一个元素,调用add方法
        public boolean add(E e) {
            return map.put(e, PRESENT)==null;
        }
        
        //-----------HashMap源码---------------------------
        
        static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
    
        static final int MAXIMUM_CAPACITY = 1 << 30;
    
        static final float DEFAULT_LOAD_FACTOR = 0.75f;
        
        transient Node<K,V>[] table;
        
        //1-2. 负载因子赋值为默认值0.75
        public HashMap() {
            this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
        }
        
        public HashMap(int initialCapacity) {
            this(initialCapacity, DEFAULT_LOAD_FACTOR);
        }
        
        public HashMap(int initialCapacity, float loadFactor) {
            if (initialCapacity < 0)
                throw new IllegalArgumentException("Illegal initial capacity: " +
                                                   initialCapacity);
            if (initialCapacity > MAXIMUM_CAPACITY)
                initialCapacity = MAXIMUM_CAPACITY;
            if (loadFactor <= 0 || Float.isNaN(loadFactor))
                throw new IllegalArgumentException("Illegal load factor: " +
                                                   loadFactor);
            this.loadFactor = loadFactor;
            this.threshold = tableSizeFor(initialCapacity);
        }
        
        //2-2. 进入HashMap的put方法中
        public V put(K key, V value) {
            //2-3. key = Student{id=1, name='lili'} value=PRESENT,对key进行hash运算
            //2-5. 走putVal方法
            return putVal(hash(key), key, value, false, true);
        }
        
        //2-4. 扰动函数,避免hash碰撞,每个版本的算法不一样。
        static final int hash(Object key) {
            int h;
            return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
        }
        
        
        final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                       boolean evict) {
            Node<K,V>[] tab; Node<K,V> p; int n, i;
            //2-5. 此时数组为空,所以进if
            if ((tab = table) == null || (n = tab.length) == 0)
                //2-6. 走resize方法,resize方法返回一个长度为16的Node[]
                //2-14. n = 16
                n = (tab = resize()).length;
                //2-15. (n - 1) & hash 根据这个表达式算出元素在数组的下标位置
                //2-16.  (p = tab[i = (n - 1) & hash]) == null 判断数组中该位置是否已经有数据了
            if ((p = tab[i = (n - 1) & hash]) == null)
                //2-17. 创建一个Node,然后放到数组对应下标的位置上
                tab[i] = newNode(hash, key, value, null);
            else {
                Node<K,V> e; K k;
                if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k))))
                    e = p;
                else if (p instanceof TreeNode)
                    e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
                else {
                    for (int binCount = 0; ; ++binCount) {
                        if ((e = p.next) == null) {
                            p.next = newNode(hash, key, value, null);
                            if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                                treeifyBin(tab, hash);
                            break;
                        }
                        if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k))))
                            break;
                        p = e;
                    }
                }
                if (e != null) { // existing mapping for key
                    V oldValue = e.value;
                    if (!onlyIfAbsent || oldValue == null)
                        e.value = value;
                    afterNodeAccess(e);
                    return oldValue;
                }
            }
            ++modCount;
            //4-1.如果超过扩容边界值12,就扩容
            if (++size > threshold)
                resize();
            afterNodeInsertion(evict);//啥也没干
            return null;
        }
        
        final Node<K,V>[] resize() {
            //2-7 oldTab = null;
            //4-2. oldTab = new Node[16];
            Node<K,V>[] oldTab = table;
            //4-3 oldCap = 16
            int oldCap = (oldTab == null) ? 0 : oldTab.length;//oldCap = 0
            //4-4 oldThr = 12
            int oldThr = threshold;// oldThr = 0;
            int newCap, newThr = 0;
            if (oldCap > 0) {
                if (oldCap >= MAXIMUM_CAPACITY) {
                    threshold = Integer.MAX_VALUE;
                    return oldTab;
                }
                //4-5. (newCap = oldCap << 1 newCap = oldCap*2=32 数组长度扩展为原来的2倍
                else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                         oldCap >= DEFAULT_INITIAL_CAPACITY)
                    newThr = oldThr << 1; // newThr=24,扩容临界也扩为原来的2倍
            }
            else if (oldThr > 0) 
                newCap = oldThr;
            else {
                //2-8. newCap = 16;            
                newCap = DEFAULT_INITIAL_CAPACITY;
                //2-9. newThr = 12;
                newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
            }
            if (newThr == 0) {
                float ft = (float)newCap * loadFactor;
                newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                          (int)ft : Integer.MAX_VALUE);
            }
            //2-10. threshold = 12
            //4-6. threshold=24
            threshold = newThr;
            @SuppressWarnings({"rawtypes","unchecked"})
            //2-11. 创建一个newTab=Node[16]的数组
            //4-7 把原来的数组扩展成一个newTab=Node[32]的数组
            Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
            //2-12.table = newTab=Node[16] 主数组长度默认为16
            table = newTab;
            //4-8.进入if
            if (oldTab != null) {
                //4-9.oldCap = 16
                
                /*
                整个循环的意思就是对于之前数组中的元素再次根据e.hash & 数组.length公式算出在扩容后的数组的下标位置,
                    1.如果当前元素没有链表,则按照e.hash & (newCap - 1),算下标位置
                    2.如果当前元素下面有链表(链表里每一个元素都重新算),则按照e.hash & oldCap,算下标位置
                         2-1.如果算出(e.hash & oldCap) == 0,则还放在原来在老数组的对应下标位置;
                         2-2.如果算出(e.hash & oldCap) != 0,则放在j + oldCap的下标位置中;
                */
                for (int j = 0; j < oldCap; ++j) {
                    Node<K,V> e;
                    if ((e = oldTab[j]) != null) {
                        oldTab[j] = null;
                        if (e.next == null)
                            newTab[e.hash & (newCap - 1)] = e;
                        //1.8 引入的红黑树
                        else if (e instanceof TreeNode)
                            ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                        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) {
                                    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;
                            }
                        }
                    }
                }
            }
            //2-13. 返回一个长度为16的Node[]
            return newTab;
        }
        
         Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
            return new Node<>(hash, key, value, next);
        }
            
        final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab,
                                           int h, K k, V v) {
                Class<?> kc = null;
                boolean searched = false;
                TreeNode<K,V> root = (parent != null) ? root() : this;
                for (TreeNode<K,V> p = root;;) {
                    int dir, ph; K pk;
                    if ((ph = p.hash) > h)
                        dir = -1;
                    else if (ph < h)
                        dir = 1;
                    else if ((pk = p.key) == k || (k != null && k.equals(pk)))
                        return p;
                    else if ((kc == null &&
                              (kc = comparableClassFor(k)) == null) ||
                             (dir = compareComparables(kc, k, pk)) == 0) {
                        if (!searched) {
                            TreeNode<K,V> q, ch;
                            searched = true;
                            if (((ch = p.left) != null &&
                                 (q = ch.find(h, k, kc)) != null) ||
                                ((ch = p.right) != null &&
                                 (q = ch.find(h, k, kc)) != null))
                                return q;
                        }
                        dir = tieBreakOrder(k, pk);
                    }
    
                    TreeNode<K,V> xp = p;
                    if ((p = (dir <= 0) ? p.left : p.right) == null) {
                        Node<K,V> xpn = xp.next;
                        TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn);
                        if (dir <= 0)
                            xp.left = x;
                        else
                            xp.right = x;
                        xp.next = x;
                        x.parent = x.prev = xp;
                        if (xpn != null)
                            ((TreeNode<K,V>)xpn).prev = x;
                        moveRootToFront(tab, balanceInsertion(root, x));
                        return null;
                    }
                }
            }
            
            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();
            else if ((e = tab[index = (n - 1) & hash]) != null) {
                TreeNode<K,V> hd = null, tl = null;
                do {
                    TreeNode<K,V> p = replacementTreeNode(e, null);
                    if (tl == null)
                        hd = p;
                    else {
                        p.prev = tl;
                        tl.next = p;
                    }
                    tl = p;
                } while ((e = e.next) != null);
                if ((tab[index] = hd) != null)
                    hd.treeify(tab);
            }
        }
        
        void afterNodeAccess(Node<K,V> p) { }
        void afterNodeInsertion(boolean evict) { }
    }
    萝莉身,御姐心。。。。。
  • 相关阅读:
    pat1038. Recover the Smallest Number (30)
    pat1037. Magic Coupon (25)
    pat1036. Boys vs Girls (25)
    pat1031. Hello World for U (20)
    pat1030. Travel Plan (30)
    pat1028. List Sorting (25)
    pat1027. Colors in Mars (20)
    pat1017. Queueing at Bank (25)
    pat1025. PAT Ranking (25)
    Reverse Linked List II
  • 原文地址:https://www.cnblogs.com/bentuzi/p/15163065.html
Copyright © 2011-2022 走看看