【源码】ArrayList、HashMap源码阅读笔记.md

简书迁移

Posted by thrfox on June 29, 2020

#ArrayList ###类注释

1
2
3
4
5
6
7
 * Hash table based implementation of the <tt>Map</tt> interface.  This
 * implementation provides all of the optional map operations, and permits
 * <tt>null</tt> values and the <tt>null</tt> key.  (The <tt>HashMap</tt>
 * class is roughly equivalent to <tt>Hashtable</tt>, except that it is
 * unsynchronized and permits nulls.)  This class makes no guarantees as to
 * the order of the map; in particular, it does not guarantee that the order
 * will remain constant over time.
  • 实现了Map接口
  • 允许key和value为null
  • 大致与HashTable相同,除了是异步且支持null
  • 不保证有序 ```
  • An instance of HashMap has two parameters that affect its

  • performance: initial capacity and load factor. The
  • capacity is the number of buckets in the hash table, and the initial
  • capacity is simply the capacity at the time the hash table is created. The
  • load factor is a measure of how full the hash table is allowed to
  • get before its capacity is automatically increased. When the number of
  • entries in the hash table exceeds the product of the load factor and the
  • current capacity, the hash table is rehashed (that is, internal data
  • structures are rebuilt) so that the hash table has approximately twice the
  • number of buckets. ```
  • 两个重要的影响性能的参数:初始容量【initial capacity】 和 载入系数【load factor】
  • …… ```
  • If no such object exists, the map should be “wrapped” using the
  • {@link Collections#synchronizedMap Collections.synchronizedMap}
  • method. This is best done at creation time, to prevent accidental
  • unsynchronized access to the map:<pre>
  • Map m = Collections.synchronizedMap(new HashMap(…));</pre> ```
  • 如果需要同步,则在创建时使用Collections.synchronizedMap(new HashMap(…)) ####Map内元素Node ``` /**
    • Basic hash bin node, used for most entries. (See below for
    • TreeNode subclass, and in LinkedHashMap for its Entry subclass.) */ static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next;

      Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; }

      public final K getKey() { return key; } public final V getValue() { return value; } public final String toString() { return key + “=” + value; }

      public final int hashCode() { return Objects.hashCode(key) ^ Objects.hashCode(value); }

      public final V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; }

      public final boolean equals(Object o) { if (o == this) return true; if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry<?,?>)o; if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) return true; } return false; } } ```

      主要方法

  • 构造器
    1
    2
    3
    4
    
    public HashMap() {
    // 此时只是将 loadFactor 置为默认值
          this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }
    
  • put
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    
      public V put(K key, V value) {
          return putVal(hash(key), key, value, false, true);
      }
    
      final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                     boolean evict) {
    // Map类中的Node对象初始化
          Node<K,V>[] tab; Node<K,V> p; int n, i;
    
          if ((tab = table) == null || (n = tab.length) == 0)
              n = (tab = resize()).length;
    // 是否是第一次put,如果是,则newNode
          if ((p = tab[i = (n - 1) & hash]) == null)
              tab[i] = newNode(hash, key, value, null);
          else {
              Node<K,V> e; K k;
    // 不是第一次put,先判断该key的Hash是否存在
              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);
    // 如果该key不存在则新增一个node到tab数组里
              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;
                  }
              }
    // 更改value值
              if (e != null) { // existing mapping for key
                  V oldValue = e.value;
                  if (!onlyIfAbsent || oldValue == null)
                      e.value = value;
                  afterNodeAccess(e);
                  return oldValue;
              }
          }
          ++modCount;
          if (++size > threshold)
              resize();
          afterNodeInsertion(evict);
          return null;
      }