#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; }