HashMap源码分析--jdk1.8 (2)

HashMap源码分析--jdk1.8


   HashMap extends AbstractMap
   AbstractMap extends Object
  java中所有类都继承Object,所以HashMap的继承结构如上图。
   1. AbstractMap是一个抽象类,实现了Map<K,V>接口,Map<K,V>定义了一些Map(K,V)键值对通用方法,而AbstractMap抽象类中可以有抽象方法,还可以有具体的实现方法,AbstractMap实现接口中一些通用的方法,实现了基础的/get/remove/containsKey/containsValue/keySet方法,HashMap再继承AbstractMap,拿到通用基础的方法,然后自己在实现一些自己特有的方法,这样的好处是:让代码更简洁,继承结构最底层的类中通用的方法,减少重复代码,从上往下,从抽象到具体,越来越丰富,可复用。
   2.HashMap实现了Map<K,V>、Cloneable、Serializable接口
     1)Map<K,V>接口,定义了Map键值对通用的方法,1.8中为了加强接口的能力,使得接口可以存在具体的方法,前提是方法需要被default或static关键字所修饰,Map中实现了一些通用方法实现,使接口更加抽象。
     2)Cloneable接口,可以使用Object.Clone()方法。
     3)Serializable接口,序列化接口,表明该类可以被序列化,什么是序列化?简单的说,就是能够从类变成字节流传输,反序列化,就是从字节流变成原来的类

HashMap核心方法分析 1. put方法(10种实现)--增/修改   

HashMap源码分析--jdk1.8


HashMap源码分析--jdk1.8


HashMap源码分析--jdk1.8


HashMap源码分析--jdk1.8

     1)V put(K key, V value);//map添加元素

/** * 新增元素 */ public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } /** * Implements Map.put and related methods * @param hash hash for key * @param key the key * @param value the value to put * @param onlyIfAbsent if true, don't change existing value * onlyIfAbsent默认传false,覆盖更改现有值 * onlyIfAbsent传true,不覆盖更改现有值 * @param evict if false, the table is in creation mode. * @return previous value, or null if none */ 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为空 或者 长度为0 if ((tab = table) == null || (n = tab.length) == 0) //扩容 n = (tab = resize()).length; //计算index,并对null做处理 // (n - 1) & hash 确定元素存放在哪个桶中,桶为空,新生成结点放入桶中(此时,这个结点是放在数组中) if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); // 桶中已经存在元素 else { Node<K,V> e; K k; //如果key存在 直接覆盖 value // 比较桶中第一个元素(数组中的结点)的hash值相等,key相等 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) // 将第一个元素赋值给e,用e来记录 e = p; //如果table[i]是红黑树 直接在红黑树中插入 // hash值不相等,即key不相等;为红黑树结点 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; } // 判断链表中结点的key值与插入的元素的key值是否相等 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) // 相等,跳出循环 break; // 用于遍历桶中的链表,与前面的e = p.next组合,可以遍历链表 p = e; } } // 表示在桶中找到key值、hash值与插入元素相等的结点 if (e != null) { // existing mapping for key // 记录e的value V oldValue = e.value; // onlyIfAbsent为false或者旧值为null if (!onlyIfAbsent || oldValue == null) //用新值替换旧值 e.value = value; // 访问后回调 afterNodeAccess(e); // 返回旧值 return oldValue; } } // 结构性修改 ++modCount; // 实际大小大于阈值则扩容 if (++size > threshold) resize(); // 插入后回调,用来回调移除最早放入Map的对象(LinkedHashMap中实现了,HashMap中为空实现) afterNodeInsertion(evict); return null; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyssgd.html