1、结构

JDK版本 实现方式 节点数>=8 节点数<=6
1.8以前 数组+单向链表 数组+单向链表 数组+单向链表
1.8以后 数组+单向链表+红黑树 数组+红黑树 数组+单向链表

1.1、1.8以前

将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可
image.png

1.2、1.8以后

JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。
image.png

1.3、hashcode

产生hash碰撞,hash码相同,则通过key的equals()方法比较值是否相同.
key值不相等:则会在该节点的链表结构上新增一个节点(如果链表长度>=8且 数组节点数>=64 链表结构就会转换成红黑树)
key值相等:则用新的value替换旧的value

什么时候会产生hash碰撞? 如何解决hash碰撞?
答:只要两个元素产生的hash值相同就会产生hash碰撞。
jdk8前采用链表解决hash碰撞、jdk8以后采用链表 + 红黑树解决hash碰撞。
image.png

2、源码

  1. public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {
  2. /*
  3. * 下面是成员属性的定义
  4. */
  5. private static final long serialVersionUID = 362498820763181265L; // 实现序列化接口的序列化默认版本号
  6. static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 默认初始容量等于16
  7. static final int MAXIMUM_CAPACITY = 1 << 30; // 2的30次方也等于 Integer.MAXVALUE
  8. static final float DEFAULT_LOAD_FACTOR = 0.75f;// 默认的扩容因子
  9. static final int TREEIFY_THRESHOLD = 8; // 红黑数的阈值,hash碰撞达到了8链表才会转换成红黑数
  10. static final int UNTREEIFY_THRESHOLD = 6;// hash碰撞小于6才解开红黑树结构转换成链表结构
  11. static final int MIN_TREEIFY_CAPACITY = 64; // 树型容量的最小值,这个值不能小于 4*TREEIFY_THRESHOLD = 32
  12. transient Node<K,V>[] table;// 真正存储数据的数组结构
  13. transient Set<Map.Entry<K,V>> entrySet;// 所有节点Entry的集合
  14. transient int size;// hashMap的大小
  15. transient int modCount;// 并发修改计数,用于检测并发修改异常的值
  16. int threshold;// 扩容的条件,threshold=0.75*容量
  17. final float loadFactor;// 加载因子,默认值为0.75.可以通过构造方法重新设定
  18. /**
  19. *
  20. * 下面的是静态内部类,可以粗略的过一眼,不用细究代码。
  21. *
  22. */
  23. // 这个结构很重要,是真正存储数据的数据结构
  24. static class Node<K,V> implements Map.Entry<K,V> {
  25. final int hash; // 存储的 hash值
  26. final K key; // 存储的 key值
  27. V value; // 存储的 value值
  28. Node<K,V> next; // 链表结构,下一个节点的数据。结合前面定义的 transient Node<K,V>[] table;因此说HashMap的存储结构是数组+链表。
  29. Node(int hash, K key, V value, Node<K,V> next) {} // 构造方法
  30. public final K getKey() {} // 获取当前节点的key
  31. public final V getValue() {} // 获取当前节点的value
  32. public final String toString() {} // 返回{key:value}的字符串
  33. public final int hashCode() {} // hash当前节点的key,value并返回hash值
  34. public final V setValue(V newValue) {} // 给节点设置value值
  35. public final boolean equals(Object o) {}// 实现equals方法用于比较o与当前节点是否相等
  36. }
  37. /*
  38. * 树节点数据结构,重要部分
  39. */
  40. static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
  41. TreeNode<K,V> parent; // 父节点
  42. TreeNode<K,V> left; // 左节点
  43. TreeNode<K,V> right; // 右节点
  44. TreeNode<K,V> prev; // 删除后需要取消链接
  45. boolean red; // 用来判断当前节点是红还是黑节点
  46. /* 构造方法,创建对象的时候数据也存进来了 */
  47. TreeNode(int hash, K key, V val, Node<K,V> next) {}
  48. // 查找节点
  49. final TreeNode<K,V> find(int h, Object k, Class<?> kc) {}
  50. // 获取红黑树中的节点
  51. final TreeNode<K,V> getTreeNode(int h, Object k) {}
  52. // 链表 转换成 红黑树
  53. final void treeify(Node<K,V>[] tab) {}
  54. // 红黑树 转换成 链表
  55. final Node<K,V> untreeify(HashMap<K,V> map) {}
  56. // 添加红黑树节点
  57. final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab,int h, K k, V v) {}
  58. // 删除红黑树节点
  59. final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab,boolean movable) {}// 移除节点
  60. final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) {} // 拆分
  61. // 左旋
  62. static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,TreeNode<K,V> p) {}
  63. // 右旋
  64. static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root,TreeNode<K,V> p) {}
  65. // 插入元素时保存平衡
  66. static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,TreeNode<K,V> x) {}
  67. // 删除元素时保存平衡
  68. static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,TreeNode<K,V> x) {}
  69. final TreeNode<K,V> root() {}
  70. static <K,V> void moveRootToFront(Node<K,V>[] tab, TreeNode<K,V> root) {}
  71. static int tieBreakOrder(Object a, Object b) {}
  72. static <K,V> boolean checkInvariants(TreeNode<K,V> t) {}
  73. }
  74. static Class<?> comparableClassFor(Object x) {/*省略*/} //
  75. //Entry集合的内部结构,其目的就是实现Set方法,方便获取Set中的Entry(实际存储的数据结构)
  76. final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
  77. public final int size(){} // Set中元素个数
  78. public final void clear(){} // 清空Set
  79. public final Iterator<Map.Entry<K,V>> iterator() {} // 迭代器,迭代获取Set内容
  80. public final boolean contains(Object o) {} // 是否包含某个元素
  81. public final boolean remove(Object o) {} // 移除某个元素
  82. public final Spliterator<Map.Entry<K,V>> spliterator() {} // 拆分Set集合,暂没有遇到使用场景。跳过
  83. public final void forEach(Consumer<? super Map.Entry<K,V>> action) {} // 遍历元素,使用函数式接口Consumer,可以使用lambda表达式进行遍历消费
  84. }
  85. /*
  86. * 下面是类迭代器分别代表hash、key、value、Entry
  87. */
  88. abstract class HashIterator {
  89. Node<K,V> next; // 下一个节点
  90. Node<K,V> current; // 当前节点
  91. int expectedModCount; // 预期的修改计数
  92. int index; // 当前索引值
  93. HashIterator() {} //构造方法
  94. public final boolean hasNext() {} // 判断是否还有下一个Node节点
  95. final Node<K,V> nextNode() {} // 返回下一个节点Node
  96. public final void remove() {} // 移除当前节点
  97. }
  98. final class KeyIterator extends HashIterator implements Iterator<K> {public final K next() { }// 返回下一个节点的 键 key}
  99. final class ValueIterator extends HashIterator implements Iterator<V> { public final V next() { }//返回下一个节点的 值 value}
  100. final class EntryIterator extends HashIterator implements Iterator<Map.Entry<K,V>> {public final Map.Entry<K,V> next() { }//返回下一个节点}
  101. /*
  102. * 下面是Spliterator和上面迭代器一样作用,
  103. * 只不是这些迭代器可以并行处理
  104. *
  105. */
  106. static class HashMapSpliterator<K,V> {
  107. final HashMap<K,V> map;
  108. Node<K,V> current; // 当前节点
  109. int index; // 当前索引
  110. int fence; // 上一个节点索引
  111. int est; // 预估值
  112. int expectedModCount; // 预期的并发修改次数
  113. //构造方法
  114. HashMapSpliterator(HashMap<K,V> m, int origin,int fence, int est,int expectedModCount) {}
  115. final int getFence() {}//返回上一个节点的索引
  116. public final long estimateSize() {} // 返回Map的预估个数
  117. }
  118. // 该类的目的是解决hashMap存储数据过大,不方便处理,对数据进行拆分,提供性能。
  119. static final class KeySpliterator<K,V> extends HashMapSpliterator<K,V> implements Spliterator<K> {
  120. // 构造方法
  121. KeySpliterator(HashMap<K,V> m, int origin, int fence, int est, int expectedModCount) {}
  122. public KeySpliterator<K,V> trySplit() {} //
  123. public void forEachRemaining(Consumer<? super K> action) {}//遍历剩余元素
  124. /*如果有剩余元素,执行Consumer操作,并返回true,否则返回false */
  125. public boolean tryAdvance(Consumer<? super K> action) {}
  126. public int characteristics() {} //特征值
  127. }
  128. static final class ValueSpliterator<K,V> extends HashMapSpliterator<K,V> implements Spliterator<V> {
  129. //
  130. ValueSpliterator(HashMap<K,V> m, int origin, int fence, int est,int expectedModCount) {}
  131. public ValueSpliterator<K,V> trySplit() {}
  132. public void forEachRemaining(Consumer<? super V> action) {}
  133. public boolean tryAdvance(Consumer<? super V> action) {}
  134. public int characteristics() {}
  135. }
  136. static final class EntrySpliterator<K,V> extends HashMapSpliterator<K,V> implements Spliterator<Map.Entry<K,V>> {
  137. public EntrySpliterator<K,V> trySplit() {}
  138. public void forEachRemaining(Consumer<? super Map.Entry<K,V>> action) {}
  139. public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) {}
  140. public int characteristics() {}
  141. }
  142. /*
  143. * 四种构造方法
  144. */
  145. public HashMap(int initialCapacity, float loadFactor) {}
  146. public HashMap(int initialCapacity) {}
  147. public HashMap() {}
  148. public HashMap(Map<? extends K, ? extends V> m) {}
  149. /*
  150. * HashMap中定义的方法
  151. */
  152. static final int tableSizeFor(int cap) {} // 得到大于cap的最佳容量值
  153. final float loadFactor() {} // 返回加载因子
  154. final int capacity() {} // 返回容量值
  155. public void clear() {} // 清空hashMap
  156. public int size() {} // 返回hashMap存储了多少个元素
  157. public boolean isEmpty() {} // 判断hashMap是否没有存储元素
  158. static final int hash(Object key) {} // 得到key的hash值
  159. /* 添加和修改 */
  160. public V put(K key, V value) {} // 存除键值对数据
  161. // 实际真正存数据的方法put方法就是调用它才真正的将key,value存入hashMap
  162. final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {}
  163. public void putAll(Map<? extends K, ? extends V> m) {} //批量添加
  164. // 查询
  165. public V get(Object key) {} // 根据key取出hashMap中的内容
  166. // 删除
  167. public V remove(Object key) {} // 删除key所对于的键值对
  168. // hashMap的扩容方法
  169. final Node<K,V>[] resize() {}
  170. public boolean containsKey(Object key) {} // 判断hashMap中是否包含key
  171. public boolean containsValue(Object value) {} // 判断hashMap中是否包含value
  172. final void treeifyBin(Node<K,V>[] tab, int hash) {}// 转换成红黑树
  173. //获取节点
  174. final Node<K,V> getNode(int hash, Object key) {}
  175. //删除节点
  176. final Node<K,V> removeNode(int hash, Object key, Object value,boolean matchValue, boolean movable) {}
  177. // 批量添加Entry
  178. final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {}
  179. public Collection<V> values() {} // 获取所有value
  180. public Set<K> keySet() {}
  181. final class KeySet extends AbstractSet<K> {}
  182. final class Values extends AbstractCollection<V> {}
  183. public Set<Map.Entry<K,V>> entrySet() {}
  184. /*
  185. * 下面是集合类作者失误导致的结果,
  186. * 不用细究,
  187. * 原因是HashMap实现了Map接口,继承的AbstractMap也实现了同样的接口
  188. * 导致出现下面这么多重写方法。(后作者发现自己的错误,想修改,但被拒绝了,因为jdk组织认为不值得修改)
  189. */
  190. @SuppressWarnings({"rawtypes","unchecked"})
  191. static int compareComparables(Class<?> kc, Object k, Object x) {}
  192. @Override
  193. public V getOrDefault(Object key, V defaultValue) {}
  194. @Override
  195. public V putIfAbsent(K key, V value) {}
  196. @Override
  197. public boolean remove(Object key, Object value) {}
  198. @Override
  199. public boolean replace(K key, V oldValue, V newValue) {}
  200. @Override
  201. public V replace(K key, V value) {}
  202. @Override
  203. public V computeIfAbsent(K key,Function<? super K, ? extends V> mappingFunction) {}
  204. public V computeIfPresent(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction) {}
  205. @Override
  206. public V compute(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction) {}
  207. @Override
  208. public V merge(K key, V value,BiFunction<? super V, ? super V, ? extends V> remappingFunction) {}
  209. @Override
  210. public void forEach(BiConsumer<? super K, ? super V> action) {}
  211. @Override
  212. public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {}
  213. @SuppressWarnings("unchecked")
  214. @Override
  215. public Object clone() {}
  216. private void writeObject(java.io.ObjectOutputStream s)}
  217. private void readObject(java.io.ObjectInputStream s)throws IOException, ClassNotFoundException {}
  218. Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {}
  219. Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {}
  220. TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {}
  221. TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {}
  222. void reinitialize() {}
  223. void afterNodeAccess(Node<K,V> p) { }
  224. void afterNodeInsertion(boolean evict) { }
  225. void afterNodeRemoval(Node<K,V> p) { }
  226. void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {}
  227. }