Java--集合--HashMap

  1. HashMap底层机制及源码剖析
    1. 理论:
    2.  源码剖析案例

      1. package com.model.map.hashmap;
        
        import java.util.HashMap;
        import java.util.HashSet;
        
        /**
         * @Description:测试类
         * @Author: 张紫韩
         * @Crete 2021/6/14 20:13
         */
        public class HashMapDemo01 {
            public static void main(String[] args) {
                HashMap<Object, Object> hashMap = new HashMap<>();
                hashMap.put("java", "java");
                hashMap.put("php", "a");
                hashMap.put("java", "JAVA");
                System.out.println(hashMap);
        
                /**
                 * 1.执行构造器 new HashMap(),初始化加载因子 loadfactor=0.75 ,HashMap$Node[] table=null
                 *     public HashMap() {
                 *         this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
                 *     }
                 * 2.执行put()
                 *     public V put(K key, V value) {
                 *         return putVal(hash(key), key, value, false, true);
                 *     }
                 *
                 *      2.1 执行hash(key),计算出key的hash值在进行^ (h >>> 16);运算,但会Hash值
                 *             static final int hash(Object key) {
                 *               int h;
                 *               return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
                 *               }
                 *
                 *      2.2执行key.hashCode(),得到hash值
                 *                  public int hashCode() {
                 *         int h = hash;
                 *         if (h == 0 && value.length > 0) {
                 *             char val[] = value;
                 *
                 *             for (int i = 0; i < value.length; i++) {
                 *                 h = 31 * h + val[i];
                 *             }
                 *             hash = h;
                 *         }
                 *         return h;
                 *     }
                 *
                 * 3.执行putVal
                 *
                 *    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                 *                    boolean evict) {
                 *
                 *          //复制变量
                 *         Node<K,V>[] tab; Node<K,V> p; int n, i;
                 *
                 *         //判断是否是第一次添加,如果是就之江将table表扩容到16
                 *         if ((tab = table) == null || (n = tab.length) == 0)
                 *             n = (tab = resize()).length;
                 *
                 *          //通过hash值计算出这个元素应该在表中的那个索引位置,通过索取到这个节点:p
                 *          //如果这 节点为 null,直接将这个元素放在这个节点上,否则进入到else中
                 *         if ((p = tab[i = (n - 1) & hash]) == null)
                 *             tab[i] = newNode(hash, key, value, null);
                 *         else {
                 *
                 *         //定义辅助变量
                 *             Node<K,V> e; K k;
                 *
                 *         //如果p的hash值和要插入的元素相等,且 两个key == 返回rue或者equals()返回true
                 *         //就将 e指向p节点
                 *             if (p.hash == hash &&
                 *                 ((k = p.key) == key || (key != null && key.equals(k))))
                 *                 e = p;
                 *
                 *             //如果p节点上是一个树,则交给putTreeVal  进行添加此元素
                 *             else if (p instanceof TreeNode)
                 *                 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
                 *             else {
                 *
                 *             //如果全上面都不满足,则这是一个链表,则进行循环遍历比较
                 *                 for (int binCount = 0; ; ++binCount) {
                 *
                 *                 //p.next==null说明链表中没有和 要添加的元素一样,直接将这个元素放在链表的末尾
                 *                     if ((e = p.next) == null) {
                 *                         p.next = newNode(hash, key, value, null);
                 *
                 *                         //如果链表长度超过8则进行树化操作
                 *                         if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                 *
                 *                         //树化:需要满组表的长度大于等于64且链表的长度大于8,如果节点数量查过8但表的长度为到64,就不进行树化而是先进行扩容
                 *                             treeifyBin(tab, hash);
                 *                         break;
                 *                     }
                 *
                 *                     //再循环过程中如果 链表中有一个和 要添加的元素相等(即hash值一样且== 或equals()返回true,则跳出循环不在添加)
                 *                     if (e.hash == hash &&
                 *                         ((k = e.key) == key || (key != null && key.equals(k))))
                 *                         break;
                 *                     p = e;
                 *                 }
                 *             }
                 *
                 *             //进行替换操作, 当跳出上面操作时,e正好是和要添加的元素一样的节点
                 *             if (e != null) { // existing mapping for key
                 *                 V oldValue = e.value;
                 *                 if (!onlyIfAbsent || oldValue == null)
                 *
                 *                 //将链表上的节点e的value替换为 要添加元素的value
                 *                     e.value = value;
                 *                 afterNodeAccess(e);
                 *                 return oldValue;
                 *             }
                 *         }
                 *
                 *         ++modCount; //操作数++
                 *         //节点数量加一,判断节点数量是否超过 了临界值
                 *         if (++size > threshold)
                 *             resize();
                 *         afterNodeInsertion(evict);
                 *         return null;
                 *     }
                 *
                 *
                 * */
            }
        }
    3.  

      Hash扩容树华

      1.  

        package com.model.map.hashmap;
        
        import java.util.HashMap;
        
        /**
         * @Description:测试类
         * @Author: 张紫韩
         * @Crete 2021/6/15 9:21
         */
        public class HashMapDemo06 {
            public static void main(String[] args) {
        
                HashMap<Object, Object> hashMap = new HashMap<>();
                for (int i = 0; i < 11; i++) {
                    hashMap.put(new ClassA(),"a");
                }
                System.out.println(hashMap);
        
                HashMap<Object, Object> hashMap1 = new HashMap<>();
                for (int i = 0; i <13; i++) {
        
                    hashMap1.put(new Integer(i), new Integer(i));
                }
            }
        }
        class ClassA{
            private String name;
        
            @Override
            public int hashCode() {
                return 100;
            }
        
            @Override
            public String toString() {
                return "ClassA{" +
                        "name='" + name + '\'' +
                        '}';
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
        
        }

         

          

          

         

         

         

         

         

            

 

posted @ 2021-06-14 21:49  张紫韩  阅读(46)  评论(0编辑  收藏  举报