容器主要包括 Collection 和 Map 两种, Collection 存储着对象的集合,而 Map 存储着键值对(两个对象)的映射表。

Collection

image.png
Collection 接口是 List、 Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。
JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如: Set和List)实现。
在 Java5 之前, Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理; 从 JDK 5.0 增加了泛型以后, Java 集合可以记住容器中对象的数据类型。

Iterator迭代器

Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。 迭代器模式,就是为容器而生。
Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
Iterator 仅用于遍历集合, Iterator 本身并不提供承装对象的能力。如果需要创建Iterator 对象,则必须有一个被迭代的集合。
集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
image.png
在调用iter.next()方法之前必须要调用iter.hasNext()进行检测。若不调用,且下一条记录无效,直接调用iter.next()会抛出NoSuchElementException异常。
Iterator可以删除集合的元素, 但是是遍历过程中通过迭代器对象的remove方法, 不是集合对象的remove方法。
如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException。

使用 foreach 循环遍历集合元素
Java 5.0 提供了 foreach 循环迭代访问 Collection和数组。
遍历操作不需获取Collection或数组的长度,无需使用索引访问元素。
遍历集合的底层调用Iterator完成操作。
foreach还可以用来遍历数组。

List

ArrayList

ArrayList:基于动态数组实现,支持快速随机访问 。RandomAccess 接口标识着该类支持快速随机访问。
image.png
数组的默认大小为 10。
ArrayList的JDK1.8之前与之后的实现区别?
JDK1.7: ArrayList像饿汉式,直接创建一个初始容量为10的数组
JDK1.8: ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加第一个元素时再创建一个始容量为10的数组
image.png
扩容
添加元素时使用 ensureCapacityInternal() 方法来保证容量足够,如果不够时,需要使用 grow() 方法进行扩容,新容量的大小为 oldCapacity + (oldCapacity >> 1) ,即 oldCapacity+oldCapacity/2。其中 oldCapacity >> 1 需要取整,所以新容量大约是旧容量的 1.5 倍左右。(oldCapacity 为偶数就是1.5 倍,为奇数就是 1.5 倍-0.5)
扩容操作需要调用 Arrays.copyOf() 把原数组整个复制到新数组中,这个操作代价很高,因此最好在创建 ArrayList 对象时就指定大概的容量大小,减少扩容操作的次数。
序列化
ArrayList 基于数组实现,并且具有动态扩容特性,因此保存元素的数组不一定都会被使用,那么就没必要全部进行序列化。
保存元素的数组 elementData 使用 transient 修饰,该关键字声明数组默认不会被序列化。
image.png
ArrayList 实现了 writeObject() 和 readObject() 来控制只序列化数组中有元素填充那部分内容。
ArrayList 不是线程安全的,Collections提供了方法synchronizedList保证list是同步线程安全的,HashMap,HashSet同样有线程安全的方法。
image.png
或者使用CopyOnWriteArrayList,CopyOnWrite容器即写时复制的容器。往一个容器添加元素的时候,不直接往当前容器Object[]添加,
而是先将当前容器Object[]进行Copy,复制出一个新的容器Object[] newElements,然后向新的容器Object[] newElements里添加元素。
添加元素后,再将原容器的引用指向新的容器setArray(newElements)。
这样做的好处是可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。
所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。
CopyOnWriteArrayList适用于读多写少的场景。

Vector

Vector:和 ArrayList 类似,但它是线程安全的。性能较差,不推荐使用。

LinkedList

LinkedList:基于双向链表实现,使用 Node 存储链表节点信息。只能顺序访问,但是可以快速地在链表中间插入和删除元素。不仅如此, LinkedList 还可以用作栈、队列和双向队列。
image.png

三者对比

ArrayList和Vector结构一样都是动态数组,区别是ArrayList是线程不安全的,Vector是线程安全的,ArrayList性能好于Vector,ArrayList是应用最多的集合。
ArrayList和LinkedList的区别是他们的数据结构不同,ArrayList是动态数组,LinkedList是双向链表,在查询操作较多,在特定位置插入数据和删除数据较少的情况下一般选用ArrayList,在特定位置插入数据,删除数据操作较多,查询较少的情况下一般选用LinkedList,但是在大多数应用中都是对查询效率要求较高,所以ArrayList集合应用更广泛一些。

Set

HashSet

HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除性能。HashSet 底层也是数组, 初始容量为16, 当如果使用率超过0.75, (160.75=12)就会扩大容量为原来的2倍。 (16扩容为32, 依次为64,128….等)
HashSet 具有以下特点:
不能保证元素的排列顺序
HashSet 不是线程安全的
集合元素可以是 null
HashSet 集合判断两个元素相等的标准: 两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
对于存放在Set容器中的对象, 对应的类一定要重写equals()和hashCode(Objectobj)方法,以实现对象相等规则。即“相等的对象必须具有相等的散列码” 。
*向HashSet中添加元素的过程:

当向 HashSet 集合中存入一个元素时, HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值, 然后根据 hashCode 值, 通过某种散列函数决定该对象在 HashSet 底层数组中的存储位置。 (这个散列函数会与底层数组的长度相计算得到在数组中的下标, 并且这种散列函数计算还尽可能保证能均匀存储元素, 越是散列分布,该散列函数设计的越好)
如果两个元素的hashCode()值相等, 会再继续调用equals方法, 如果equals方法结果为true, 添加失败; 如果为false, 那么会保存该元素, 但是该数组的位置已经有元素了,那么会通过链表的方式继续链接。
如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等, hashSet 将会把它们存储在不同的位置,但依然可以添加成功。

LinkedHashSet

LinkedHashSet 是 HashSet 的子类
LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入
顺序保存的。
LinkedHashSet插入性能略低于 HashSet, 但在迭代访问 Set 里的全部元素时有很好的性能。
LinkedHashSet 不允许集合元素重复。

TreeSet

TreeSet 是 SortedSet 接口的实现类, TreeSet 可以确保集合元素处于排序状态。
TreeSet底层使用红黑树结构存储数据
TreeSet 两种排序方法: 自然排序定制排序。默认情况下, TreeSet 采用自然排序。

Queue

LinkedList:可以用它来实现双向队列。
PriorityQueue:基于堆结构实现,可以用它来实现优先队列。

Map

image.png

HashMap

  1. public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {
  2. private static final long serialVersionUID = 362498820763181265L;
  3. /**
  4. * hashMap 哈希桶数组的默认大小 16
  5. */
  6. static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
  7. /**
  8. * 哈希桶数组的最大值
  9. */
  10. static final int MAXIMUM_CAPACITY = 1 << 30;
  11. /**
  12. * 负载因子
  13. */
  14. static final float DEFAULT_LOAD_FACTOR = 0.75f;
  15. /**
  16. * 链表长度大于 8 ,转化成红黑树
  17. */
  18. static final int TREEIFY_THRESHOLD = 8;
  19. /**
  20. * 红黑树的node节点小于 6 是转化为链表
  21. */
  22. static final int UNTREEIFY_THRESHOLD = 6;
  23. /**
  24. * 链表转化为红黑树,哈希桶数组的大小至少为64,如果小于64,要先进行扩容,扩容之后,数组的大小大于64,链表的长度大于8,转化为红黑树
  25. */
  26. static final int MIN_TREEIFY_CAPACITY = 64;
  27. /**
  28. * Node是HashMap的一个内部类,实现了Map.Entry接口,本质是就是一个映射(键值对)。哈希数组存储的就是一个Node对象。
  29. */
  30. static class Node<K,V> implements Map.Entry<K,V> {
  31. final int hash;
  32. final K key;
  33. V value;
  34. Node<K,V> next;
  35. Node(int hash, K key, V value, Node<K,V> next) {...}
  36. public final K getKey() { ... }
  37. public final V getValue() { ... }
  38. public final String toString() { ... }
  39. public final int hashCode() {... }
  40. public final V setValue(V newValue) { ... }
  41. public final boolean equals(Object o) { ... }
  42. }
  43. /**
  44. * 计算哈希值
  45. */
  46. static final int hash(Object key) {
  47. int h;
  48. return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
  49. }
  50. /**
  51. * 把给定值转化为2的n次幂
  52. */
  53. static final int tableSizeFor(int cap) {
  54. int n = cap - 1;
  55. n |= n >>> 1;
  56. n |= n >>> 2;
  57. n |= n >>> 4;
  58. n |= n >>> 8;
  59. n |= n >>> 16;
  60. return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
  61. }
  62. /**
  63. * 存储元素的数组,总是2的n次幂
  64. */
  65. transient Node<K,V>[] table;
  66. /**
  67. * 存储具体元素的集
  68. */
  69. transient Set<Map.Entry<K,V>> entrySet;
  70. /**
  71. * HashMap中存储的键值对的数量
  72. */
  73. transient int size;
  74. /**
  75. * HashMap扩容和结构改变的次数。主要用于迭代的快速失败
  76. */
  77. transient int modCount;
  78. /**
  79. * 扩容的临界值, =容量*填充因子
  80. */
  81. int threshold;
  82. /**
  83. * 填充因子
  84. */
  85. final float loadFactor;
  86. /**
  87. * 根据key获取value
  88. */
  89. public V get(Object key) {
  90. Node<K,V> e;
  91. return (e = getNode(hash(key), key)) == null ? null : e.value;
  92. }
  93. final Node<K,V> getNode(int hash, Object key) {
  94. Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
  95. if ((tab = table) != null && (n = tab.length) > 0 &&
  96. (first = tab[(n - 1) & hash]) != null) {
  97. if (first.hash == hash && // always check first node
  98. ((k = first.key) == key || (key != null && key.equals(k))))
  99. return first;
  100. if ((e = first.next) != null) {
  101. if (first instanceof TreeNode)
  102. return ((TreeNode<K,V>)first).getTreeNode(hash, key);
  103. do {
  104. if (e.hash == hash &&
  105. ((k = e.key) == key || (key != null && key.equals(k))))
  106. return e;
  107. } while ((e = e.next) != null);
  108. }
  109. }
  110. return null;
  111. }
  112. /**
  113. * 添加数据
  114. */
  115. public V put(K key, V value) {
  116. return putVal(hash(key), key, value, false, true);
  117. }
  118. final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
  119. boolean evict) {
  120. Node<K,V>[] tab; Node<K,V> p; int n, i;
  121. // 步骤1:tab为空则创建
  122. if ((tab = table) == null || (n = tab.length) == 0)
  123. n = (tab = resize()).length;
  124. // 步骤2:计算index,如果当前位置==null,直接插入
  125. if ((p = tab[i = (n - 1) & hash]) == null)
  126. tab[i] = newNode(hash, key, value, null);
  127. else {
  128. Node<K,V> e; K k;
  129. // 步骤3:节点key存在,直接覆盖value
  130. if (p.hash == hash &&
  131. ((k = p.key) == key || (key != null && key.equals(k))))
  132. e = p;
  133. // 步骤4:判断该链为红黑树
  134. else if (p instanceof TreeNode)
  135. e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
  136. // 步骤5:该链为链表
  137. else {
  138. for (int binCount = 0; ; ++binCount) {
  139. if ((e = p.next) == null) {
  140. p.next = newNode(hash, key, value, null);
  141. //链表长度大于8转换为红黑树进行处理
  142. if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
  143. treeifyBin(tab, hash);
  144. break;
  145. }
  146. // key已经存在直接覆盖value
  147. if (e.hash == hash &&
  148. ((k = e.key) == key || (key != null && key.equals(k))))
  149. break;
  150. p = e;
  151. }
  152. }
  153. if (e != null) { // existing mapping for key
  154. V oldValue = e.value;
  155. if (!onlyIfAbsent || oldValue == null)
  156. e.value = value;
  157. afterNodeAccess(e);
  158. return oldValue;
  159. }
  160. }
  161. ++modCount;
  162. // 步骤6:超过最大容量 就扩容
  163. if (++size > threshold)
  164. resize();
  165. afterNodeInsertion(evict);
  166. return null;
  167. }
  168. /**
  169. * 扩容
  170. */
  171. final Node<K,V>[] resize() {
  172. Node<K,V>[] oldTab = table;
  173. int oldCap = (oldTab == null) ? 0 : oldTab.length;
  174. int oldThr = threshold;
  175. int newCap, newThr = 0;
  176. if (oldCap > 0) {
  177. // 超过最大值就不再扩充了,就只好随你碰撞去吧
  178. if (oldCap >= MAXIMUM_CAPACITY) {
  179. threshold = Integer.MAX_VALUE;
  180. return oldTab;
  181. }
  182. // 没超过最大值,就扩充为原来的2倍
  183. else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
  184. oldCap >= DEFAULT_INITIAL_CAPACITY)
  185. newThr = oldThr << 1; // double threshold
  186. }
  187. else if (oldThr > 0) // initial capacity was placed in threshold
  188. newCap = oldThr;
  189. else { // zero initial threshold signifies using defaults
  190. newCap = DEFAULT_INITIAL_CAPACITY;
  191. newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
  192. }
  193. if (newThr == 0) {
  194. float ft = (float)newCap * loadFactor;
  195. newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
  196. (int)ft : Integer.MAX_VALUE);
  197. }
  198. threshold = newThr;
  199. @SuppressWarnings({"rawtypes","unchecked"})
  200. Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
  201. table = newTab;
  202. if (oldTab != null) {
  203. for (int j = 0; j < oldCap; ++j) {
  204. Node<K,V> e;
  205. if ((e = oldTab[j]) != null) {
  206. oldTab[j] = null;
  207. if (e.next == null)
  208. newTab[e.hash & (newCap - 1)] = e;
  209. else if (e instanceof TreeNode)
  210. ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
  211. else { // preserve order
  212. Node<K,V> loHead = null, loTail = null;
  213. Node<K,V> hiHead = null, hiTail = null;
  214. Node<K,V> next;
  215. do {
  216. next = e.next;
  217. if ((e.hash & oldCap) == 0) {
  218. if (loTail == null)
  219. loHead = e;
  220. else
  221. loTail.next = e;
  222. loTail = e;
  223. }
  224. else {
  225. if (hiTail == null)
  226. hiHead = e;
  227. else
  228. hiTail.next = e;
  229. hiTail = e;
  230. }
  231. } while ((e = next) != null);
  232. if (loTail != null) {
  233. loTail.next = null;
  234. newTab[j] = loHead;
  235. }
  236. if (hiTail != null) {
  237. hiTail.next = null;
  238. newTab[j + oldCap] = hiHead;
  239. }
  240. }
  241. }
  242. }
  243. }
  244. return newTab;
  245. }
  246. /**
  247. * Replaces all linked nodes in bin at index for given hash unless
  248. * table is too small, in which case resizes instead.
  249. */
  250. final void treeifyBin(Node<K,V>[] tab, int hash) {
  251. int n, index; Node<K,V> e;
  252. if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
  253. resize();
  254. else if ((e = tab[index = (n - 1) & hash]) != null) {
  255. TreeNode<K,V> hd = null, tl = null;
  256. do {
  257. TreeNode<K,V> p = replacementTreeNode(e, null);
  258. if (tl == null)
  259. hd = p;
  260. else {
  261. p.prev = tl;
  262. tl.next = p;
  263. }
  264. tl = p;
  265. } while ((e = e.next) != null);
  266. if ((tab[index] = hd) != null)
  267. hd.treeify(tab);
  268. }
  269. }
  270. /**
  271. * 向hashMap中添加Map
  272. */
  273. public void putAll(Map<? extends K, ? extends V> m) {
  274. putMapEntries(m, true);
  275. }
  276. /**
  277. * 移除指定的key
  278. */
  279. public V remove(Object key) {
  280. Node<K,V> e;
  281. return (e = removeNode(hash(key), key, null, false, true)) == null ?
  282. null : e.value;
  283. }
  284. final Node<K,V> removeNode(int hash, Object key, Object value,
  285. boolean matchValue, boolean movable) {
  286. Node<K,V>[] tab; Node<K,V> p; int n, index;
  287. if ((tab = table) != null && (n = tab.length) > 0 &&
  288. (p = tab[index = (n - 1) & hash]) != null) {
  289. Node<K,V> node = null, e; K k; V v;
  290. if (p.hash == hash &&
  291. ((k = p.key) == key || (key != null && key.equals(k))))
  292. node = p;
  293. else if ((e = p.next) != null) {
  294. if (p instanceof TreeNode)
  295. node = ((TreeNode<K,V>)p).getTreeNode(hash, key);
  296. else {
  297. do {
  298. if (e.hash == hash &&
  299. ((k = e.key) == key ||
  300. (key != null && key.equals(k)))) {
  301. node = e;
  302. break;
  303. }
  304. p = e;
  305. } while ((e = e.next) != null);
  306. }
  307. }
  308. if (node != null && (!matchValue || (v = node.value) == value ||
  309. (value != null && value.equals(v)))) {
  310. if (node instanceof TreeNode)
  311. ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);
  312. else if (node == p)
  313. tab[index] = node.next;
  314. else
  315. p.next = node.next;
  316. ++modCount;
  317. --size;
  318. afterNodeRemoval(node);
  319. return node;
  320. }
  321. }
  322. return null;
  323. }
  324. /**
  325. * 清空Map
  326. */
  327. public void clear() {
  328. Node<K,V>[] tab;
  329. modCount++;
  330. if ((tab = table) != null && size > 0) {
  331. size = 0;
  332. for (int i = 0; i < tab.length; ++i)
  333. tab[i] = null;
  334. }
  335. }
  336. /**
  337. * Returns <tt>true</tt> if this map maps one or more keys to the
  338. * specified value.
  339. *
  340. * @param value value whose presence in this map is to be tested
  341. * @return <tt>true</tt> if this map maps one or more keys to the
  342. * specified value
  343. */
  344. public boolean containsValue(Object value) {
  345. Node<K,V>[] tab; V v;
  346. if ((tab = table) != null && size > 0) {
  347. for (int i = 0; i < tab.length; ++i) {
  348. for (Node<K,V> e = tab[i]; e != null; e = e.next) {
  349. if ((v = e.value) == value ||
  350. (value != null && value.equals(v)))
  351. return true;
  352. }
  353. }
  354. }
  355. return false;
  356. }
  357. /**
  358. * Returns a {@link Set} view of the keys contained in this map.
  359. * The set is backed by the map, so changes to the map are
  360. * reflected in the set, and vice-versa. If the map is modified
  361. * while an iteration over the set is in progress (except through
  362. * the iterator's own <tt>remove</tt> operation), the results of
  363. * the iteration are undefined. The set supports element removal,
  364. * which removes the corresponding mapping from the map, via the
  365. * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
  366. * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
  367. * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
  368. * operations.
  369. *
  370. * @return a set view of the keys contained in this map
  371. */
  372. public Set<K> keySet() {
  373. Set<K> ks;
  374. return (ks = keySet) == null ? (keySet = new KeySet()) : ks;
  375. }
  376. final class KeySet extends AbstractSet<K> {
  377. public final int size() { return size; }
  378. public final void clear() { HashMap.this.clear(); }
  379. public final Iterator<K> iterator() { return new KeyIterator(); }
  380. public final boolean contains(Object o) { return containsKey(o); }
  381. public final boolean remove(Object key) {
  382. return removeNode(hash(key), key, null, false, true) != null;
  383. }
  384. public final Spliterator<K> spliterator() {
  385. return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
  386. }
  387. public final void forEach(Consumer<? super K> action) {
  388. Node<K,V>[] tab;
  389. if (action == null)
  390. throw new NullPointerException();
  391. if (size > 0 && (tab = table) != null) {
  392. int mc = modCount;
  393. for (int i = 0; i < tab.length; ++i) {
  394. for (Node<K,V> e = tab[i]; e != null; e = e.next)
  395. action.accept(e.key);
  396. }
  397. if (modCount != mc)
  398. throw new ConcurrentModificationException();
  399. }
  400. }
  401. }
  402. /**
  403. * Returns a {@link Collection} view of the values contained in this map.
  404. * The collection is backed by the map, so changes to the map are
  405. * reflected in the collection, and vice-versa. If the map is
  406. * modified while an iteration over the collection is in progress
  407. * (except through the iterator's own <tt>remove</tt> operation),
  408. * the results of the iteration are undefined. The collection
  409. * supports element removal, which removes the corresponding
  410. * mapping from the map, via the <tt>Iterator.remove</tt>,
  411. * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
  412. * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not
  413. * support the <tt>add</tt> or <tt>addAll</tt> operations.
  414. *
  415. * @return a view of the values contained in this map
  416. */
  417. public Collection<V> values() {
  418. Collection<V> vs;
  419. return (vs = values) == null ? (values = new Values()) : vs;
  420. }
  421. final class Values extends AbstractCollection<V> {
  422. public final int size() { return size; }
  423. public final void clear() { HashMap.this.clear(); }
  424. public final Iterator<V> iterator() { return new ValueIterator(); }
  425. public final boolean contains(Object o) { return containsValue(o); }
  426. public final Spliterator<V> spliterator() {
  427. return new ValueSpliterator<>(HashMap.this, 0, -1, 0, 0);
  428. }
  429. public final void forEach(Consumer<? super V> action) {
  430. Node<K,V>[] tab;
  431. if (action == null)
  432. throw new NullPointerException();
  433. if (size > 0 && (tab = table) != null) {
  434. int mc = modCount;
  435. for (int i = 0; i < tab.length; ++i) {
  436. for (Node<K,V> e = tab[i]; e != null; e = e.next)
  437. action.accept(e.value);
  438. }
  439. if (modCount != mc)
  440. throw new ConcurrentModificationException();
  441. }
  442. }
  443. }
  444. /**
  445. * Returns a {@link Set} view of the mappings contained in this map.
  446. * The set is backed by the map, so changes to the map are
  447. * reflected in the set, and vice-versa. If the map is modified
  448. * while an iteration over the set is in progress (except through
  449. * the iterator's own <tt>remove</tt> operation, or through the
  450. * <tt>setValue</tt> operation on a map entry returned by the
  451. * iterator) the results of the iteration are undefined. The set
  452. * supports element removal, which removes the corresponding
  453. * mapping from the map, via the <tt>Iterator.remove</tt>,
  454. * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
  455. * <tt>clear</tt> operations. It does not support the
  456. * <tt>add</tt> or <tt>addAll</tt> operations.
  457. *
  458. * @return a set view of the mappings contained in this map
  459. */
  460. public Set<Map.Entry<K,V>> entrySet() {
  461. Set<Map.Entry<K,V>> es;
  462. return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
  463. }
  464. final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
  465. public final int size() { return size; }
  466. public final void clear() { HashMap.this.clear(); }
  467. public final Iterator<Map.Entry<K,V>> iterator() {
  468. return new EntryIterator();
  469. }
  470. public final boolean contains(Object o) {
  471. if (!(o instanceof Map.Entry))
  472. return false;
  473. Map.Entry<?,?> e = (Map.Entry<?,?>) o;
  474. Object key = e.getKey();
  475. Node<K,V> candidate = getNode(hash(key), key);
  476. return candidate != null && candidate.equals(e);
  477. }
  478. public final boolean remove(Object o) {
  479. if (o instanceof Map.Entry) {
  480. Map.Entry<?,?> e = (Map.Entry<?,?>) o;
  481. Object key = e.getKey();
  482. Object value = e.getValue();
  483. return removeNode(hash(key), key, value, true, true) != null;
  484. }
  485. return false;
  486. }
  487. public final Spliterator<Map.Entry<K,V>> spliterator() {
  488. return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);
  489. }
  490. public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
  491. Node<K,V>[] tab;
  492. if (action == null)
  493. throw new NullPointerException();
  494. if (size > 0 && (tab = table) != null) {
  495. int mc = modCount;
  496. for (int i = 0; i < tab.length; ++i) {
  497. for (Node<K,V> e = tab[i]; e != null; e = e.next)
  498. action.accept(e);
  499. }
  500. if (modCount != mc)
  501. throw new ConcurrentModificationException();
  502. }
  503. }
  504. }
  505. // Overrides of JDK8 Map extension methods
  506. @Override
  507. public V getOrDefault(Object key, V defaultValue) {
  508. Node<K,V> e;
  509. return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;
  510. }
  511. @Override
  512. public V putIfAbsent(K key, V value) {
  513. return putVal(hash(key), key, value, true, true);
  514. }
  515. @Override
  516. public boolean remove(Object key, Object value) {
  517. return removeNode(hash(key), key, value, true, true) != null;
  518. }
  519. @Override
  520. public boolean replace(K key, V oldValue, V newValue) {
  521. Node<K,V> e; V v;
  522. if ((e = getNode(hash(key), key)) != null &&
  523. ((v = e.value) == oldValue || (v != null && v.equals(oldValue)))) {
  524. e.value = newValue;
  525. afterNodeAccess(e);
  526. return true;
  527. }
  528. return false;
  529. }
  530. @Override
  531. public V replace(K key, V value) {
  532. Node<K,V> e;
  533. if ((e = getNode(hash(key), key)) != null) {
  534. V oldValue = e.value;
  535. e.value = value;
  536. afterNodeAccess(e);
  537. return oldValue;
  538. }
  539. return null;
  540. }
  541. @Override
  542. public V computeIfAbsent(K key,
  543. Function<? super K, ? extends V> mappingFunction) {
  544. if (mappingFunction == null)
  545. throw new NullPointerException();
  546. int hash = hash(key);
  547. Node<K,V>[] tab; Node<K,V> first; int n, i;
  548. int binCount = 0;
  549. TreeNode<K,V> t = null;
  550. Node<K,V> old = null;
  551. if (size > threshold || (tab = table) == null ||
  552. (n = tab.length) == 0)
  553. n = (tab = resize()).length;
  554. if ((first = tab[i = (n - 1) & hash]) != null) {
  555. if (first instanceof TreeNode)
  556. old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key);
  557. else {
  558. Node<K,V> e = first; K k;
  559. do {
  560. if (e.hash == hash &&
  561. ((k = e.key) == key || (key != null && key.equals(k)))) {
  562. old = e;
  563. break;
  564. }
  565. ++binCount;
  566. } while ((e = e.next) != null);
  567. }
  568. V oldValue;
  569. if (old != null && (oldValue = old.value) != null) {
  570. afterNodeAccess(old);
  571. return oldValue;
  572. }
  573. }
  574. V v = mappingFunction.apply(key);
  575. if (v == null) {
  576. return null;
  577. } else if (old != null) {
  578. old.value = v;
  579. afterNodeAccess(old);
  580. return v;
  581. }
  582. else if (t != null)
  583. t.putTreeVal(this, tab, hash, key, v);
  584. else {
  585. tab[i] = newNode(hash, key, v, first);
  586. if (binCount >= TREEIFY_THRESHOLD - 1)
  587. treeifyBin(tab, hash);
  588. }
  589. ++modCount;
  590. ++size;
  591. afterNodeInsertion(true);
  592. return v;
  593. }
  594. public V computeIfPresent(K key,
  595. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  596. if (remappingFunction == null)
  597. throw new NullPointerException();
  598. Node<K,V> e; V oldValue;
  599. int hash = hash(key);
  600. if ((e = getNode(hash, key)) != null &&
  601. (oldValue = e.value) != null) {
  602. V v = remappingFunction.apply(key, oldValue);
  603. if (v != null) {
  604. e.value = v;
  605. afterNodeAccess(e);
  606. return v;
  607. }
  608. else
  609. removeNode(hash, key, null, false, true);
  610. }
  611. return null;
  612. }
  613. @Override
  614. public V compute(K key,
  615. BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  616. if (remappingFunction == null)
  617. throw new NullPointerException();
  618. int hash = hash(key);
  619. Node<K,V>[] tab; Node<K,V> first; int n, i;
  620. int binCount = 0;
  621. TreeNode<K,V> t = null;
  622. Node<K,V> old = null;
  623. if (size > threshold || (tab = table) == null ||
  624. (n = tab.length) == 0)
  625. n = (tab = resize()).length;
  626. if ((first = tab[i = (n - 1) & hash]) != null) {
  627. if (first instanceof TreeNode)
  628. old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key);
  629. else {
  630. Node<K,V> e = first; K k;
  631. do {
  632. if (e.hash == hash &&
  633. ((k = e.key) == key || (key != null && key.equals(k)))) {
  634. old = e;
  635. break;
  636. }
  637. ++binCount;
  638. } while ((e = e.next) != null);
  639. }
  640. }
  641. V oldValue = (old == null) ? null : old.value;
  642. V v = remappingFunction.apply(key, oldValue);
  643. if (old != null) {
  644. if (v != null) {
  645. old.value = v;
  646. afterNodeAccess(old);
  647. }
  648. else
  649. removeNode(hash, key, null, false, true);
  650. }
  651. else if (v != null) {
  652. if (t != null)
  653. t.putTreeVal(this, tab, hash, key, v);
  654. else {
  655. tab[i] = newNode(hash, key, v, first);
  656. if (binCount >= TREEIFY_THRESHOLD - 1)
  657. treeifyBin(tab, hash);
  658. }
  659. ++modCount;
  660. ++size;
  661. afterNodeInsertion(true);
  662. }
  663. return v;
  664. }
  665. @Override
  666. public V merge(K key, V value,
  667. BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
  668. if (value == null)
  669. throw new NullPointerException();
  670. if (remappingFunction == null)
  671. throw new NullPointerException();
  672. int hash = hash(key);
  673. Node<K,V>[] tab; Node<K,V> first; int n, i;
  674. int binCount = 0;
  675. TreeNode<K,V> t = null;
  676. Node<K,V> old = null;
  677. if (size > threshold || (tab = table) == null ||
  678. (n = tab.length) == 0)
  679. n = (tab = resize()).length;
  680. if ((first = tab[i = (n - 1) & hash]) != null) {
  681. if (first instanceof TreeNode)
  682. old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key);
  683. else {
  684. Node<K,V> e = first; K k;
  685. do {
  686. if (e.hash == hash &&
  687. ((k = e.key) == key || (key != null && key.equals(k)))) {
  688. old = e;
  689. break;
  690. }
  691. ++binCount;
  692. } while ((e = e.next) != null);
  693. }
  694. }
  695. if (old != null) {
  696. V v;
  697. if (old.value != null)
  698. v = remappingFunction.apply(old.value, value);
  699. else
  700. v = value;
  701. if (v != null) {
  702. old.value = v;
  703. afterNodeAccess(old);
  704. }
  705. else
  706. removeNode(hash, key, null, false, true);
  707. return v;
  708. }
  709. if (value != null) {
  710. if (t != null)
  711. t.putTreeVal(this, tab, hash, key, value);
  712. else {
  713. tab[i] = newNode(hash, key, value, first);
  714. if (binCount >= TREEIFY_THRESHOLD - 1)
  715. treeifyBin(tab, hash);
  716. }
  717. ++modCount;
  718. ++size;
  719. afterNodeInsertion(true);
  720. }
  721. return value;
  722. }
  723. @Override
  724. public void forEach(BiConsumer<? super K, ? super V> action) {
  725. Node<K,V>[] tab;
  726. if (action == null)
  727. throw new NullPointerException();
  728. if (size > 0 && (tab = table) != null) {
  729. int mc = modCount;
  730. for (int i = 0; i < tab.length; ++i) {
  731. for (Node<K,V> e = tab[i]; e != null; e = e.next)
  732. action.accept(e.key, e.value);
  733. }
  734. if (modCount != mc)
  735. throw new ConcurrentModificationException();
  736. }
  737. }
  738. @Override
  739. public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
  740. Node<K,V>[] tab;
  741. if (function == null)
  742. throw new NullPointerException();
  743. if (size > 0 && (tab = table) != null) {
  744. int mc = modCount;
  745. for (int i = 0; i < tab.length; ++i) {
  746. for (Node<K,V> e = tab[i]; e != null; e = e.next) {
  747. e.value = function.apply(e.key, e.value);
  748. }
  749. }
  750. if (modCount != mc)
  751. throw new ConcurrentModificationException();
  752. }
  753. }
  754. /* ------------------------------------------------------------ */
  755. // Cloning and serialization
  756. /**
  757. * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and
  758. * values themselves are not cloned.
  759. *
  760. * @return a shallow copy of this map
  761. */
  762. @SuppressWarnings("unchecked")
  763. @Override
  764. public Object clone() {
  765. HashMap<K,V> result;
  766. try {
  767. result = (HashMap<K,V>)super.clone();
  768. } catch (CloneNotSupportedException e) {
  769. // this shouldn't happen, since we are Cloneable
  770. throw new InternalError(e);
  771. }
  772. result.reinitialize();
  773. result.putMapEntries(this, false);
  774. return result;
  775. }
  776. // These methods are also used when serializing HashSets
  777. final float loadFactor() { return loadFactor; }
  778. final int capacity() {
  779. return (table != null) ? table.length :
  780. (threshold > 0) ? threshold :
  781. DEFAULT_INITIAL_CAPACITY;
  782. }
  783. /**
  784. * Save the state of the <tt>HashMap</tt> instance to a stream (i.e.,
  785. * serialize it).
  786. *
  787. * @serialData The <i>capacity</i> of the HashMap (the length of the
  788. * bucket array) is emitted (int), followed by the
  789. * <i>size</i> (an int, the number of key-value
  790. * mappings), followed by the key (Object) and value (Object)
  791. * for each key-value mapping. The key-value mappings are
  792. * emitted in no particular order.
  793. */
  794. private void writeObject(java.io.ObjectOutputStream s)
  795. throws IOException {
  796. int buckets = capacity();
  797. // Write out the threshold, loadfactor, and any hidden stuff
  798. s.defaultWriteObject();
  799. s.writeInt(buckets);
  800. s.writeInt(size);
  801. internalWriteEntries(s);
  802. }
  803. /**
  804. * Reconstitute the {@code HashMap} instance from a stream (i.e.,
  805. * deserialize it).
  806. */
  807. private void readObject(java.io.ObjectInputStream s)
  808. throws IOException, ClassNotFoundException {
  809. // Read in the threshold (ignored), loadfactor, and any hidden stuff
  810. s.defaultReadObject();
  811. reinitialize();
  812. if (loadFactor <= 0 || Float.isNaN(loadFactor))
  813. throw new InvalidObjectException("Illegal load factor: " +
  814. loadFactor);
  815. s.readInt(); // Read and ignore number of buckets
  816. int mappings = s.readInt(); // Read number of mappings (size)
  817. if (mappings < 0)
  818. throw new InvalidObjectException("Illegal mappings count: " +
  819. mappings);
  820. else if (mappings > 0) { // (if zero, use defaults)
  821. // Size the table using given load factor only if within
  822. // range of 0.25...4.0
  823. float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
  824. float fc = (float)mappings / lf + 1.0f;
  825. int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
  826. DEFAULT_INITIAL_CAPACITY :
  827. (fc >= MAXIMUM_CAPACITY) ?
  828. MAXIMUM_CAPACITY :
  829. tableSizeFor((int)fc));
  830. float ft = (float)cap * lf;
  831. threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
  832. (int)ft : Integer.MAX_VALUE);
  833. @SuppressWarnings({"rawtypes","unchecked"})
  834. Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
  835. table = tab;
  836. // Read the keys and values, and put the mappings in the HashMap
  837. for (int i = 0; i < mappings; i++) {
  838. @SuppressWarnings("unchecked")
  839. K key = (K) s.readObject();
  840. @SuppressWarnings("unchecked")
  841. V value = (V) s.readObject();
  842. putVal(hash(key), key, value, false, false);
  843. }
  844. }
  845. }
  846. /* ------------------------------------------------------------ */
  847. // iterators
  848. abstract class HashIterator {
  849. Node<K,V> next; // next entry to return
  850. Node<K,V> current; // current entry
  851. int expectedModCount; // for fast-fail
  852. int index; // current slot
  853. HashIterator() {
  854. expectedModCount = modCount;
  855. Node<K,V>[] t = table;
  856. current = next = null;
  857. index = 0;
  858. if (t != null && size > 0) { // advance to first entry
  859. do {} while (index < t.length && (next = t[index++]) == null);
  860. }
  861. }
  862. public final boolean hasNext() {
  863. return next != null;
  864. }
  865. final Node<K,V> nextNode() {
  866. Node<K,V>[] t;
  867. Node<K,V> e = next;
  868. if (modCount != expectedModCount)
  869. throw new ConcurrentModificationException();
  870. if (e == null)
  871. throw new NoSuchElementException();
  872. if ((next = (current = e).next) == null && (t = table) != null) {
  873. do {} while (index < t.length && (next = t[index++]) == null);
  874. }
  875. return e;
  876. }
  877. public final void remove() {
  878. Node<K,V> p = current;
  879. if (p == null)
  880. throw new IllegalStateException();
  881. if (modCount != expectedModCount)
  882. throw new ConcurrentModificationException();
  883. current = null;
  884. K key = p.key;
  885. removeNode(hash(key), key, null, false, false);
  886. expectedModCount = modCount;
  887. }
  888. }
  889. final class KeyIterator extends HashIterator
  890. implements Iterator<K> {
  891. public final K next() { return nextNode().key; }
  892. }
  893. final class ValueIterator extends HashIterator
  894. implements Iterator<V> {
  895. public final V next() { return nextNode().value; }
  896. }
  897. final class EntryIterator extends HashIterator
  898. implements Iterator<Map.Entry<K,V>> {
  899. public final Map.Entry<K,V> next() { return nextNode(); }
  900. }
  901. /* ------------------------------------------------------------ */
  902. // spliterators
  903. static class HashMapSpliterator<K,V> {
  904. final HashMap<K,V> map;
  905. Node<K,V> current; // current node
  906. int index; // current index, modified on advance/split
  907. int fence; // one past last index
  908. int est; // size estimate
  909. int expectedModCount; // for comodification checks
  910. HashMapSpliterator(HashMap<K,V> m, int origin,
  911. int fence, int est,
  912. int expectedModCount) {
  913. this.map = m;
  914. this.index = origin;
  915. this.fence = fence;
  916. this.est = est;
  917. this.expectedModCount = expectedModCount;
  918. }
  919. final int getFence() { // initialize fence and size on first use
  920. int hi;
  921. if ((hi = fence) < 0) {
  922. HashMap<K,V> m = map;
  923. est = m.size;
  924. expectedModCount = m.modCount;
  925. Node<K,V>[] tab = m.table;
  926. hi = fence = (tab == null) ? 0 : tab.length;
  927. }
  928. return hi;
  929. }
  930. public final long estimateSize() {
  931. getFence(); // force init
  932. return (long) est;
  933. }
  934. }
  935. static final class KeySpliterator<K,V>
  936. extends HashMapSpliterator<K,V>
  937. implements Spliterator<K> {
  938. KeySpliterator(HashMap<K,V> m, int origin, int fence, int est,
  939. int expectedModCount) {
  940. super(m, origin, fence, est, expectedModCount);
  941. }
  942. public KeySpliterator<K,V> trySplit() {
  943. int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
  944. return (lo >= mid || current != null) ? null :
  945. new KeySpliterator<>(map, lo, index = mid, est >>>= 1,
  946. expectedModCount);
  947. }
  948. public void forEachRemaining(Consumer<? super K> action) {
  949. int i, hi, mc;
  950. if (action == null)
  951. throw new NullPointerException();
  952. HashMap<K,V> m = map;
  953. Node<K,V>[] tab = m.table;
  954. if ((hi = fence) < 0) {
  955. mc = expectedModCount = m.modCount;
  956. hi = fence = (tab == null) ? 0 : tab.length;
  957. }
  958. else
  959. mc = expectedModCount;
  960. if (tab != null && tab.length >= hi &&
  961. (i = index) >= 0 && (i < (index = hi) || current != null)) {
  962. Node<K,V> p = current;
  963. current = null;
  964. do {
  965. if (p == null)
  966. p = tab[i++];
  967. else {
  968. action.accept(p.key);
  969. p = p.next;
  970. }
  971. } while (p != null || i < hi);
  972. if (m.modCount != mc)
  973. throw new ConcurrentModificationException();
  974. }
  975. }
  976. public boolean tryAdvance(Consumer<? super K> action) {
  977. int hi;
  978. if (action == null)
  979. throw new NullPointerException();
  980. Node<K,V>[] tab = map.table;
  981. if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {
  982. while (current != null || index < hi) {
  983. if (current == null)
  984. current = tab[index++];
  985. else {
  986. K k = current.key;
  987. current = current.next;
  988. action.accept(k);
  989. if (map.modCount != expectedModCount)
  990. throw new ConcurrentModificationException();
  991. return true;
  992. }
  993. }
  994. }
  995. return false;
  996. }
  997. public int characteristics() {
  998. return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |
  999. Spliterator.DISTINCT;
  1000. }
  1001. }
  1002. static final class ValueSpliterator<K,V>
  1003. extends HashMapSpliterator<K,V>
  1004. implements Spliterator<V> {
  1005. ValueSpliterator(HashMap<K,V> m, int origin, int fence, int est,
  1006. int expectedModCount) {
  1007. super(m, origin, fence, est, expectedModCount);
  1008. }
  1009. public ValueSpliterator<K,V> trySplit() {
  1010. int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
  1011. return (lo >= mid || current != null) ? null :
  1012. new ValueSpliterator<>(map, lo, index = mid, est >>>= 1,
  1013. expectedModCount);
  1014. }
  1015. public void forEachRemaining(Consumer<? super V> action) {
  1016. int i, hi, mc;
  1017. if (action == null)
  1018. throw new NullPointerException();
  1019. HashMap<K,V> m = map;
  1020. Node<K,V>[] tab = m.table;
  1021. if ((hi = fence) < 0) {
  1022. mc = expectedModCount = m.modCount;
  1023. hi = fence = (tab == null) ? 0 : tab.length;
  1024. }
  1025. else
  1026. mc = expectedModCount;
  1027. if (tab != null && tab.length >= hi &&
  1028. (i = index) >= 0 && (i < (index = hi) || current != null)) {
  1029. Node<K,V> p = current;
  1030. current = null;
  1031. do {
  1032. if (p == null)
  1033. p = tab[i++];
  1034. else {
  1035. action.accept(p.value);
  1036. p = p.next;
  1037. }
  1038. } while (p != null || i < hi);
  1039. if (m.modCount != mc)
  1040. throw new ConcurrentModificationException();
  1041. }
  1042. }
  1043. public boolean tryAdvance(Consumer<? super V> action) {
  1044. int hi;
  1045. if (action == null)
  1046. throw new NullPointerException();
  1047. Node<K,V>[] tab = map.table;
  1048. if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {
  1049. while (current != null || index < hi) {
  1050. if (current == null)
  1051. current = tab[index++];
  1052. else {
  1053. V v = current.value;
  1054. current = current.next;
  1055. action.accept(v);
  1056. if (map.modCount != expectedModCount)
  1057. throw new ConcurrentModificationException();
  1058. return true;
  1059. }
  1060. }
  1061. }
  1062. return false;
  1063. }
  1064. public int characteristics() {
  1065. return (fence < 0 || est == map.size ? Spliterator.SIZED : 0);
  1066. }
  1067. }
  1068. static final class EntrySpliterator<K,V>
  1069. extends HashMapSpliterator<K,V>
  1070. implements Spliterator<Map.Entry<K,V>> {
  1071. EntrySpliterator(HashMap<K,V> m, int origin, int fence, int est,
  1072. int expectedModCount) {
  1073. super(m, origin, fence, est, expectedModCount);
  1074. }
  1075. public EntrySpliterator<K,V> trySplit() {
  1076. int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
  1077. return (lo >= mid || current != null) ? null :
  1078. new EntrySpliterator<>(map, lo, index = mid, est >>>= 1,
  1079. expectedModCount);
  1080. }
  1081. public void forEachRemaining(Consumer<? super Map.Entry<K,V>> action) {
  1082. int i, hi, mc;
  1083. if (action == null)
  1084. throw new NullPointerException();
  1085. HashMap<K,V> m = map;
  1086. Node<K,V>[] tab = m.table;
  1087. if ((hi = fence) < 0) {
  1088. mc = expectedModCount = m.modCount;
  1089. hi = fence = (tab == null) ? 0 : tab.length;
  1090. }
  1091. else
  1092. mc = expectedModCount;
  1093. if (tab != null && tab.length >= hi &&
  1094. (i = index) >= 0 && (i < (index = hi) || current != null)) {
  1095. Node<K,V> p = current;
  1096. current = null;
  1097. do {
  1098. if (p == null)
  1099. p = tab[i++];
  1100. else {
  1101. action.accept(p);
  1102. p = p.next;
  1103. }
  1104. } while (p != null || i < hi);
  1105. if (m.modCount != mc)
  1106. throw new ConcurrentModificationException();
  1107. }
  1108. }
  1109. public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) {
  1110. int hi;
  1111. if (action == null)
  1112. throw new NullPointerException();
  1113. Node<K,V>[] tab = map.table;
  1114. if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {
  1115. while (current != null || index < hi) {
  1116. if (current == null)
  1117. current = tab[index++];
  1118. else {
  1119. Node<K,V> e = current;
  1120. current = current.next;
  1121. action.accept(e);
  1122. if (map.modCount != expectedModCount)
  1123. throw new ConcurrentModificationException();
  1124. return true;
  1125. }
  1126. }
  1127. }
  1128. return false;
  1129. }
  1130. public int characteristics() {
  1131. return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |
  1132. Spliterator.DISTINCT;
  1133. }
  1134. }
  1135. /* ------------------------------------------------------------ */
  1136. // LinkedHashMap support
  1137. /*
  1138. * The following package-protected methods are designed to be
  1139. * overridden by LinkedHashMap, but not by any other subclass.
  1140. * Nearly all other internal methods are also package-protected
  1141. * but are declared final, so can be used by LinkedHashMap, view
  1142. * classes, and HashSet.
  1143. */
  1144. // Create a regular (non-tree) node
  1145. Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
  1146. return new Node<>(hash, key, value, next);
  1147. }
  1148. // For conversion from TreeNodes to plain nodes
  1149. Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {
  1150. return new Node<>(p.hash, p.key, p.value, next);
  1151. }
  1152. // Create a tree bin node
  1153. TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
  1154. return new TreeNode<>(hash, key, value, next);
  1155. }
  1156. // For treeifyBin
  1157. TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
  1158. return new TreeNode<>(p.hash, p.key, p.value, next);
  1159. }
  1160. /**
  1161. * Reset to initial default state. Called by clone and readObject.
  1162. */
  1163. void reinitialize() {
  1164. table = null;
  1165. entrySet = null;
  1166. keySet = null;
  1167. values = null;
  1168. modCount = 0;
  1169. threshold = 0;
  1170. size = 0;
  1171. }
  1172. // Callbacks to allow LinkedHashMap post-actions
  1173. void afterNodeAccess(Node<K,V> p) { }
  1174. void afterNodeInsertion(boolean evict) { }
  1175. void afterNodeRemoval(Node<K,V> p) { }
  1176. // Called only from writeObject, to ensure compatible ordering.
  1177. void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
  1178. Node<K,V>[] tab;
  1179. if (size > 0 && (tab = table) != null) {
  1180. for (int i = 0; i < tab.length; ++i) {
  1181. for (Node<K,V> e = tab[i]; e != null; e = e.next) {
  1182. s.writeObject(e.key);
  1183. s.writeObject(e.value);
  1184. }
  1185. }
  1186. }
  1187. }
  1188. /* ------------------------------------------------------------ */
  1189. // Tree bins
  1190. /**
  1191. * Entry for Tree bins. Extends LinkedHashMap.Entry (which in turn
  1192. * extends Node) so can be used as extension of either regular or
  1193. * linked node.
  1194. */
  1195. static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
  1196. TreeNode<K,V> parent; // red-black tree links
  1197. TreeNode<K,V> left;
  1198. TreeNode<K,V> right;
  1199. TreeNode<K,V> prev; // needed to unlink next upon deletion
  1200. boolean red;
  1201. TreeNode(int hash, K key, V val, Node<K,V> next) {
  1202. super(hash, key, val, next);
  1203. }
  1204. /**
  1205. * Returns root of tree containing this node.
  1206. */
  1207. final TreeNode<K,V> root() {
  1208. for (TreeNode<K,V> r = this, p;;) {
  1209. if ((p = r.parent) == null)
  1210. return r;
  1211. r = p;
  1212. }
  1213. }
  1214. /**
  1215. * Ensures that the given root is the first node of its bin.
  1216. */
  1217. static <K,V> void moveRootToFront(Node<K,V>[] tab, TreeNode<K,V> root) {
  1218. int n;
  1219. if (root != null && tab != null && (n = tab.length) > 0) {
  1220. int index = (n - 1) & root.hash;
  1221. TreeNode<K,V> first = (TreeNode<K,V>)tab[index];
  1222. if (root != first) {
  1223. Node<K,V> rn;
  1224. tab[index] = root;
  1225. TreeNode<K,V> rp = root.prev;
  1226. if ((rn = root.next) != null)
  1227. ((TreeNode<K,V>)rn).prev = rp;
  1228. if (rp != null)
  1229. rp.next = rn;
  1230. if (first != null)
  1231. first.prev = root;
  1232. root.next = first;
  1233. root.prev = null;
  1234. }
  1235. assert checkInvariants(root);
  1236. }
  1237. }
  1238. /**
  1239. * Finds the node starting at root p with the given hash and key.
  1240. * The kc argument caches comparableClassFor(key) upon first use
  1241. * comparing keys.
  1242. */
  1243. final TreeNode<K,V> find(int h, Object k, Class<?> kc) {
  1244. TreeNode<K,V> p = this;
  1245. do {
  1246. int ph, dir; K pk;
  1247. TreeNode<K,V> pl = p.left, pr = p.right, q;
  1248. if ((ph = p.hash) > h)
  1249. p = pl;
  1250. else if (ph < h)
  1251. p = pr;
  1252. else if ((pk = p.key) == k || (k != null && k.equals(pk)))
  1253. return p;
  1254. else if (pl == null)
  1255. p = pr;
  1256. else if (pr == null)
  1257. p = pl;
  1258. else if ((kc != null ||
  1259. (kc = comparableClassFor(k)) != null) &&
  1260. (dir = compareComparables(kc, k, pk)) != 0)
  1261. p = (dir < 0) ? pl : pr;
  1262. else if ((q = pr.find(h, k, kc)) != null)
  1263. return q;
  1264. else
  1265. p = pl;
  1266. } while (p != null);
  1267. return null;
  1268. }
  1269. /**
  1270. * Calls find for root node.
  1271. */
  1272. final TreeNode<K,V> getTreeNode(int h, Object k) {
  1273. return ((parent != null) ? root() : this).find(h, k, null);
  1274. }
  1275. /**
  1276. * Tie-breaking utility for ordering insertions when equal
  1277. * hashCodes and non-comparable. We don't require a total
  1278. * order, just a consistent insertion rule to maintain
  1279. * equivalence across rebalancings. Tie-breaking further than
  1280. * necessary simplifies testing a bit.
  1281. */
  1282. static int tieBreakOrder(Object a, Object b) {
  1283. int d;
  1284. if (a == null || b == null ||
  1285. (d = a.getClass().getName().
  1286. compareTo(b.getClass().getName())) == 0)
  1287. d = (System.identityHashCode(a) <= System.identityHashCode(b) ?
  1288. -1 : 1);
  1289. return d;
  1290. }
  1291. /**
  1292. * Forms tree of the nodes linked from this node.
  1293. * @return root of tree
  1294. */
  1295. final void treeify(Node<K,V>[] tab) {
  1296. TreeNode<K,V> root = null;
  1297. for (TreeNode<K,V> x = this, next; x != null; x = next) {
  1298. next = (TreeNode<K,V>)x.next;
  1299. x.left = x.right = null;
  1300. if (root == null) {
  1301. x.parent = null;
  1302. x.red = false;
  1303. root = x;
  1304. }
  1305. else {
  1306. K k = x.key;
  1307. int h = x.hash;
  1308. Class<?> kc = null;
  1309. for (TreeNode<K,V> p = root;;) {
  1310. int dir, ph;
  1311. K pk = p.key;
  1312. if ((ph = p.hash) > h)
  1313. dir = -1;
  1314. else if (ph < h)
  1315. dir = 1;
  1316. else if ((kc == null &&
  1317. (kc = comparableClassFor(k)) == null) ||
  1318. (dir = compareComparables(kc, k, pk)) == 0)
  1319. dir = tieBreakOrder(k, pk);
  1320. TreeNode<K,V> xp = p;
  1321. if ((p = (dir <= 0) ? p.left : p.right) == null) {
  1322. x.parent = xp;
  1323. if (dir <= 0)
  1324. xp.left = x;
  1325. else
  1326. xp.right = x;
  1327. root = balanceInsertion(root, x);
  1328. break;
  1329. }
  1330. }
  1331. }
  1332. }
  1333. moveRootToFront(tab, root);
  1334. }
  1335. /**
  1336. * Returns a list of non-TreeNodes replacing those linked from
  1337. * this node.
  1338. */
  1339. final Node<K,V> untreeify(HashMap<K,V> map) {
  1340. Node<K,V> hd = null, tl = null;
  1341. for (Node<K,V> q = this; q != null; q = q.next) {
  1342. Node<K,V> p = map.replacementNode(q, null);
  1343. if (tl == null)
  1344. hd = p;
  1345. else
  1346. tl.next = p;
  1347. tl = p;
  1348. }
  1349. return hd;
  1350. }
  1351. /**
  1352. * Tree version of putVal.
  1353. */
  1354. final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab,
  1355. int h, K k, V v) {
  1356. Class<?> kc = null;
  1357. boolean searched = false;
  1358. TreeNode<K,V> root = (parent != null) ? root() : this;
  1359. for (TreeNode<K,V> p = root;;) {
  1360. int dir, ph; K pk;
  1361. if ((ph = p.hash) > h)
  1362. dir = -1;
  1363. else if (ph < h)
  1364. dir = 1;
  1365. else if ((pk = p.key) == k || (k != null && k.equals(pk)))
  1366. return p;
  1367. else if ((kc == null &&
  1368. (kc = comparableClassFor(k)) == null) ||
  1369. (dir = compareComparables(kc, k, pk)) == 0) {
  1370. if (!searched) {
  1371. TreeNode<K,V> q, ch;
  1372. searched = true;
  1373. if (((ch = p.left) != null &&
  1374. (q = ch.find(h, k, kc)) != null) ||
  1375. ((ch = p.right) != null &&
  1376. (q = ch.find(h, k, kc)) != null))
  1377. return q;
  1378. }
  1379. dir = tieBreakOrder(k, pk);
  1380. }
  1381. TreeNode<K,V> xp = p;
  1382. if ((p = (dir <= 0) ? p.left : p.right) == null) {
  1383. Node<K,V> xpn = xp.next;
  1384. TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn);
  1385. if (dir <= 0)
  1386. xp.left = x;
  1387. else
  1388. xp.right = x;
  1389. xp.next = x;
  1390. x.parent = x.prev = xp;
  1391. if (xpn != null)
  1392. ((TreeNode<K,V>)xpn).prev = x;
  1393. moveRootToFront(tab, balanceInsertion(root, x));
  1394. return null;
  1395. }
  1396. }
  1397. }
  1398. /**
  1399. * Removes the given node, that must be present before this call.
  1400. * This is messier than typical red-black deletion code because we
  1401. * cannot swap the contents of an interior node with a leaf
  1402. * successor that is pinned by "next" pointers that are accessible
  1403. * independently during traversal. So instead we swap the tree
  1404. * linkages. If the current tree appears to have too few nodes,
  1405. * the bin is converted back to a plain bin. (The test triggers
  1406. * somewhere between 2 and 6 nodes, depending on tree structure).
  1407. */
  1408. final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab,
  1409. boolean movable) {
  1410. int n;
  1411. if (tab == null || (n = tab.length) == 0)
  1412. return;
  1413. int index = (n - 1) & hash;
  1414. TreeNode<K,V> first = (TreeNode<K,V>)tab[index], root = first, rl;
  1415. TreeNode<K,V> succ = (TreeNode<K,V>)next, pred = prev;
  1416. if (pred == null)
  1417. tab[index] = first = succ;
  1418. else
  1419. pred.next = succ;
  1420. if (succ != null)
  1421. succ.prev = pred;
  1422. if (first == null)
  1423. return;
  1424. if (root.parent != null)
  1425. root = root.root();
  1426. if (root == null || root.right == null ||
  1427. (rl = root.left) == null || rl.left == null) {
  1428. tab[index] = first.untreeify(map); // too small
  1429. return;
  1430. }
  1431. TreeNode<K,V> p = this, pl = left, pr = right, replacement;
  1432. if (pl != null && pr != null) {
  1433. TreeNode<K,V> s = pr, sl;
  1434. while ((sl = s.left) != null) // find successor
  1435. s = sl;
  1436. boolean c = s.red; s.red = p.red; p.red = c; // swap colors
  1437. TreeNode<K,V> sr = s.right;
  1438. TreeNode<K,V> pp = p.parent;
  1439. if (s == pr) { // p was s's direct parent
  1440. p.parent = s;
  1441. s.right = p;
  1442. }
  1443. else {
  1444. TreeNode<K,V> sp = s.parent;
  1445. if ((p.parent = sp) != null) {
  1446. if (s == sp.left)
  1447. sp.left = p;
  1448. else
  1449. sp.right = p;
  1450. }
  1451. if ((s.right = pr) != null)
  1452. pr.parent = s;
  1453. }
  1454. p.left = null;
  1455. if ((p.right = sr) != null)
  1456. sr.parent = p;
  1457. if ((s.left = pl) != null)
  1458. pl.parent = s;
  1459. if ((s.parent = pp) == null)
  1460. root = s;
  1461. else if (p == pp.left)
  1462. pp.left = s;
  1463. else
  1464. pp.right = s;
  1465. if (sr != null)
  1466. replacement = sr;
  1467. else
  1468. replacement = p;
  1469. }
  1470. else if (pl != null)
  1471. replacement = pl;
  1472. else if (pr != null)
  1473. replacement = pr;
  1474. else
  1475. replacement = p;
  1476. if (replacement != p) {
  1477. TreeNode<K,V> pp = replacement.parent = p.parent;
  1478. if (pp == null)
  1479. root = replacement;
  1480. else if (p == pp.left)
  1481. pp.left = replacement;
  1482. else
  1483. pp.right = replacement;
  1484. p.left = p.right = p.parent = null;
  1485. }
  1486. TreeNode<K,V> r = p.red ? root : balanceDeletion(root, replacement);
  1487. if (replacement == p) { // detach
  1488. TreeNode<K,V> pp = p.parent;
  1489. p.parent = null;
  1490. if (pp != null) {
  1491. if (p == pp.left)
  1492. pp.left = null;
  1493. else if (p == pp.right)
  1494. pp.right = null;
  1495. }
  1496. }
  1497. if (movable)
  1498. moveRootToFront(tab, r);
  1499. }
  1500. /**
  1501. * Splits nodes in a tree bin into lower and upper tree bins,
  1502. * or untreeifies if now too small. Called only from resize;
  1503. * see above discussion about split bits and indices.
  1504. *
  1505. * @param map the map
  1506. * @param tab the table for recording bin heads
  1507. * @param index the index of the table being split
  1508. * @param bit the bit of hash to split on
  1509. */
  1510. final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) {
  1511. TreeNode<K,V> b = this;
  1512. // Relink into lo and hi lists, preserving order
  1513. TreeNode<K,V> loHead = null, loTail = null;
  1514. TreeNode<K,V> hiHead = null, hiTail = null;
  1515. int lc = 0, hc = 0;
  1516. for (TreeNode<K,V> e = b, next; e != null; e = next) {
  1517. next = (TreeNode<K,V>)e.next;
  1518. e.next = null;
  1519. if ((e.hash & bit) == 0) {
  1520. if ((e.prev = loTail) == null)
  1521. loHead = e;
  1522. else
  1523. loTail.next = e;
  1524. loTail = e;
  1525. ++lc;
  1526. }
  1527. else {
  1528. if ((e.prev = hiTail) == null)
  1529. hiHead = e;
  1530. else
  1531. hiTail.next = e;
  1532. hiTail = e;
  1533. ++hc;
  1534. }
  1535. }
  1536. if (loHead != null) {
  1537. if (lc <= UNTREEIFY_THRESHOLD)
  1538. tab[index] = loHead.untreeify(map);
  1539. else {
  1540. tab[index] = loHead;
  1541. if (hiHead != null) // (else is already treeified)
  1542. loHead.treeify(tab);
  1543. }
  1544. }
  1545. if (hiHead != null) {
  1546. if (hc <= UNTREEIFY_THRESHOLD)
  1547. tab[index + bit] = hiHead.untreeify(map);
  1548. else {
  1549. tab[index + bit] = hiHead;
  1550. if (loHead != null)
  1551. hiHead.treeify(tab);
  1552. }
  1553. }
  1554. }
  1555. /* ------------------------------------------------------------ */
  1556. // Red-black tree methods, all adapted from CLR
  1557. static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,
  1558. TreeNode<K,V> p) {
  1559. TreeNode<K,V> r, pp, rl;
  1560. if (p != null && (r = p.right) != null) {
  1561. if ((rl = p.right = r.left) != null)
  1562. rl.parent = p;
  1563. if ((pp = r.parent = p.parent) == null)
  1564. (root = r).red = false;
  1565. else if (pp.left == p)
  1566. pp.left = r;
  1567. else
  1568. pp.right = r;
  1569. r.left = p;
  1570. p.parent = r;
  1571. }
  1572. return root;
  1573. }
  1574. static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root,
  1575. TreeNode<K,V> p) {
  1576. TreeNode<K,V> l, pp, lr;
  1577. if (p != null && (l = p.left) != null) {
  1578. if ((lr = p.left = l.right) != null)
  1579. lr.parent = p;
  1580. if ((pp = l.parent = p.parent) == null)
  1581. (root = l).red = false;
  1582. else if (pp.right == p)
  1583. pp.right = l;
  1584. else
  1585. pp.left = l;
  1586. l.right = p;
  1587. p.parent = l;
  1588. }
  1589. return root;
  1590. }
  1591. static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,
  1592. TreeNode<K,V> x) {
  1593. x.red = true;
  1594. for (TreeNode<K,V> xp, xpp, xppl, xppr;;) {
  1595. if ((xp = x.parent) == null) {
  1596. x.red = false;
  1597. return x;
  1598. }
  1599. else if (!xp.red || (xpp = xp.parent) == null)
  1600. return root;
  1601. if (xp == (xppl = xpp.left)) {
  1602. if ((xppr = xpp.right) != null && xppr.red) {
  1603. xppr.red = false;
  1604. xp.red = false;
  1605. xpp.red = true;
  1606. x = xpp;
  1607. }
  1608. else {
  1609. if (x == xp.right) {
  1610. root = rotateLeft(root, x = xp);
  1611. xpp = (xp = x.parent) == null ? null : xp.parent;
  1612. }
  1613. if (xp != null) {
  1614. xp.red = false;
  1615. if (xpp != null) {
  1616. xpp.red = true;
  1617. root = rotateRight(root, xpp);
  1618. }
  1619. }
  1620. }
  1621. }
  1622. else {
  1623. if (xppl != null && xppl.red) {
  1624. xppl.red = false;
  1625. xp.red = false;
  1626. xpp.red = true;
  1627. x = xpp;
  1628. }
  1629. else {
  1630. if (x == xp.left) {
  1631. root = rotateRight(root, x = xp);
  1632. xpp = (xp = x.parent) == null ? null : xp.parent;
  1633. }
  1634. if (xp != null) {
  1635. xp.red = false;
  1636. if (xpp != null) {
  1637. xpp.red = true;
  1638. root = rotateLeft(root, xpp);
  1639. }
  1640. }
  1641. }
  1642. }
  1643. }
  1644. }
  1645. static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
  1646. TreeNode<K,V> x) {
  1647. for (TreeNode<K,V> xp, xpl, xpr;;) {
  1648. if (x == null || x == root)
  1649. return root;
  1650. else if ((xp = x.parent) == null) {
  1651. x.red = false;
  1652. return x;
  1653. }
  1654. else if (x.red) {
  1655. x.red = false;
  1656. return root;
  1657. }
  1658. else if ((xpl = xp.left) == x) {
  1659. if ((xpr = xp.right) != null && xpr.red) {
  1660. xpr.red = false;
  1661. xp.red = true;
  1662. root = rotateLeft(root, xp);
  1663. xpr = (xp = x.parent) == null ? null : xp.right;
  1664. }
  1665. if (xpr == null)
  1666. x = xp;
  1667. else {
  1668. TreeNode<K,V> sl = xpr.left, sr = xpr.right;
  1669. if ((sr == null || !sr.red) &&
  1670. (sl == null || !sl.red)) {
  1671. xpr.red = true;
  1672. x = xp;
  1673. }
  1674. else {
  1675. if (sr == null || !sr.red) {
  1676. if (sl != null)
  1677. sl.red = false;
  1678. xpr.red = true;
  1679. root = rotateRight(root, xpr);
  1680. xpr = (xp = x.parent) == null ?
  1681. null : xp.right;
  1682. }
  1683. if (xpr != null) {
  1684. xpr.red = (xp == null) ? false : xp.red;
  1685. if ((sr = xpr.right) != null)
  1686. sr.red = false;
  1687. }
  1688. if (xp != null) {
  1689. xp.red = false;
  1690. root = rotateLeft(root, xp);
  1691. }
  1692. x = root;
  1693. }
  1694. }
  1695. }
  1696. else { // symmetric
  1697. if (xpl != null && xpl.red) {
  1698. xpl.red = false;
  1699. xp.red = true;
  1700. root = rotateRight(root, xp);
  1701. xpl = (xp = x.parent) == null ? null : xp.left;
  1702. }
  1703. if (xpl == null)
  1704. x = xp;
  1705. else {
  1706. TreeNode<K,V> sl = xpl.left, sr = xpl.right;
  1707. if ((sl == null || !sl.red) &&
  1708. (sr == null || !sr.red)) {
  1709. xpl.red = true;
  1710. x = xp;
  1711. }
  1712. else {
  1713. if (sl == null || !sl.red) {
  1714. if (sr != null)
  1715. sr.red = false;
  1716. xpl.red = true;
  1717. root = rotateLeft(root, xpl);
  1718. xpl = (xp = x.parent) == null ?
  1719. null : xp.left;
  1720. }
  1721. if (xpl != null) {
  1722. xpl.red = (xp == null) ? false : xp.red;
  1723. if ((sl = xpl.left) != null)
  1724. sl.red = false;
  1725. }
  1726. if (xp != null) {
  1727. xp.red = false;
  1728. root = rotateRight(root, xp);
  1729. }
  1730. x = root;
  1731. }
  1732. }
  1733. }
  1734. }
  1735. }
  1736. /**
  1737. * Recursive invariant check
  1738. */
  1739. static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
  1740. TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,
  1741. tb = t.prev, tn = (TreeNode<K,V>)t.next;
  1742. if (tb != null && tb.next != t)
  1743. return false;
  1744. if (tn != null && tn.prev != t)
  1745. return false;
  1746. if (tp != null && t != tp.left && t != tp.right)
  1747. return false;
  1748. if (tl != null && (tl.parent != t || tl.hash > t.hash))
  1749. return false;
  1750. if (tr != null && (tr.parent != t || tr.hash < t.hash))
  1751. return false;
  1752. if (t.red && tl != null && tl.red && tr != null && tr.red)
  1753. return false;
  1754. if (tl != null && !checkInvariants(tl))
  1755. return false;
  1756. if (tr != null && !checkInvariants(tr))
  1757. return false;
  1758. return true;
  1759. }
  1760. }
  1761. }

HashMap是 Map 接口使用频率最高的实现类。
允许使用null键和null值,与HashSet一样,不保证映射的顺序。
所有的key构成的集合是Set:无序的、不可重复的。所以, key所在的类要重写:equals()和hashCode()
所有的value构成的集合是Collection:无序的、可以重复的。所以, value所在的类要重写: equals()
一个key-value构成一个entry
所有的entry构成的集合是Set:无序的、不可重复的
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。
JDK 7及以前版本: HashMap是数组+链表结构(即为链地址法)
JDK 8版本发布以后: HashMap是数组+链表+红黑树实现。
HashMap源码中的重要常量
DEFAULT_INITIAL_CAPACITY : HashMap的默认容量, 16
MAXIMUM_CAPACITY : HashMap的最大支持容量, 2^30
DEFAULT_LOAD_FACTOR: HashMap的默认加载因子
TREEIFY_THRESHOLD: Bucket中链表长度大于该默认值,转化为红黑树
UNTREEIFY_THRESHOLD: Bucket中红黑树存储的Node小于该默认值,转化为链表
MIN_TREEIFY_CAPACITY: 桶中的Node被树化时最小的hash表容量。(当桶中Node的
数量大到需要变红黑树时,若hash表容量小于MIN_TREEIFY_CAPACITY时,此时应执行resize扩容操作这个MIN_TREEIFY_CAPACITY的值至少是TREEIFY_THRESHOLD的4倍。)
table: 存储元素的数组,总是2的n次幂
entrySet: 存储具体元素的集
size: HashMap中存储的键值对的数量
modCount: HashMap扩容和结构改变的次数。
threshold: 扩容的临界值, =容量*填充因子
loadFactor: 填充因子
在HashMap中,哈希桶数组table的长度length大小必须为2的n次方(一定是合数),这是一种非常规的设计,常规的设计是把桶的大小设计为素数。
当HashMap中的其中一个链的对象个数如果达到了8个,此时如果capacity没有达到64,那么HashMap会先扩容解决,如果已经达到了64,那么这个链会变成树,结点类型由Node变成TreeNode类型。当然,如果当映射关系被移除后,下次resize方法时判断树的结点个数低于6个,也会把树再转为链表。

LinkedHashMap

LinkedHashMap 是 HashMap 的子类。
在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序或者 LRU 顺序 。
与LinkedHashSet类似, LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致。

TreeMap

TreeMap存储 Key-Value 对时, 需要根据 key-value 对进行排序。
TreeMap 可以保证所有的 Key-Value 对处于有序状态。
TreeSet底层使用红黑树结构存储数据
TreeMap 的 Key 的排序:
自然排序: TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现
Comparable 接口
TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。

Hashtable

Hashtable是个古老的 Map 实现类, JDK1.0就提供了。不同于HashMap,Hashtable是线程安全的。
性能较弱,不推荐使用。

ConcurrentHashMap

ConcurrentHashMap 和 HashMap 实现上类似,最主要的差别是 ConcurrentHashMap 采用了了分段锁(Segment),每个分段锁维护着几个桶(HashEntry),多个线程可以同时访问不同分段锁上的桶,从而使其并发度更高(并发度就是 Segment 的个数)。
Segment 继承自 ReentrantLock。 默认的并发级别为 16,也就是说默认创建 16 个 Segment。
JDK 1.7 使用分段锁机制来实现并发更新操作,核心类为 Segment,它继承自重入锁 ReentrantLock,并发度与 Segment 数量量相等。
JDK 1.8 使用了 CAS 操作来支持更高的并发度,在 CAS 操作失败时使用内置锁 synchronized。并且 JDK 1.8 的实现也在链表过长时会转换为红黑树。

WeakHashMap

WeakHashMap 的 Entry 继承自 WeakReference,被 WeakReference 关联的对象在下一次垃圾回收时会被回收。
WeakHashMap 主要用来实现缓存,通过使用 WeakHashMap 来引用缓存对象,由 JVM 对这部分缓存进行回收。