不含红黑树部分

    1. import java.util.Map;
    2. import java.util.Objects;
    3. /**
    4. * @author : fuyuaaa
    5. * @date : 2021-01-29 16:29
    6. */
    7. @SuppressWarnings("all")
    8. public class MyHashMap<K, V> {
    9. /**
    10. * 默认初始容量,必须是2的指数值
    11. */
    12. static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
    13. /**
    14. * 最大容量, 默认是2的30次方
    15. */
    16. static final int MAXIMUM_CAPACITY = 1 << 30;
    17. /**
    18. * 负载因子,当size达到 容量*负载因子 时 会触发扩容
    19. */
    20. static final float DEFAULT_LOAD_FACTOR = 0.75f;
    21. /**
    22. * 树化阈值
    23. */
    24. static final int TREEIFY_THRESHOLD = 8;
    25. /**
    26. * 取消树化的阈值
    27. */
    28. static final int UNTREEIFY_THRESHOLD = 6;
    29. /**
    30. * 当容量大于该值时,才进行树化
    31. */
    32. static final int MIN_TREEIFY_CAPACITY = 64;
    33. /**
    34. *
    35. */
    36. static class Node<K, V> implements Map.Entry<K, V> {
    37. // 当前key的hash值
    38. final int hash;
    39. final K key;
    40. V value;
    41. // 后继指针
    42. Node<K, V> next;
    43. Node(int hash, K key, V value, Node<K, V> next) {
    44. this.hash = hash;
    45. this.key = key;
    46. this.value = value;
    47. this.next = next;
    48. }
    49. public final K getKey() {
    50. return key;
    51. }
    52. public final V getValue() {
    53. return value;
    54. }
    55. public final String toString() {
    56. return key + "=" + value;
    57. }
    58. public final int hashCode() {
    59. return Objects.hashCode(key) ^ Objects.hashCode(value);
    60. }
    61. public final V setValue(V newValue) {
    62. V oldValue = value;
    63. value = newValue;
    64. return oldValue;
    65. }
    66. public final boolean equals(Object o) {
    67. if (o == this)
    68. return true;
    69. if (o instanceof Map.Entry) {
    70. Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
    71. if (Objects.equals(key, e.getKey()) &&
    72. Objects.equals(value, e.getValue()))
    73. return true;
    74. }
    75. return false;
    76. }
    77. }
    78. /* ---------------- Static utilities -------------- */
    79. /**
    80. * 计算key的hash值。
    81. * (h = key.hashCode()) ^ (h >>> 16)
    82. * 计算余数 (n-1) & hash 时,由于 n 比较小,hash 只有低位参与了计算,高位的计算可以认为是无效的。
    83. * 这样导致了计算结果只与低位信息有关,高位数据没发挥作用。
    84. * 为了处理这个缺陷,让高位数据与低位数据进行异或,以此加大低位信息的随机性,变相的让高位数据参与到计算中。
    85. */
    86. static final int hash(Object key) {
    87. int h;
    88. return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    89. }
    90. /**
    91. * 根据给定的容量重新计算table的容量,结果是2的指数值,如果是7则会变成8。
    92. */
    93. static final int tableSizeFor(int cap) {
    94. int n = cap - 1;
    95. n |= n >>> 1;
    96. n |= n >>> 2;
    97. n |= n >>> 4;
    98. n |= n >>> 8;
    99. n |= n >>> 16;
    100. return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    101. }
    102. /**
    103. * 存储数据的table,在初次使用时会初始化,大小为2的指数值
    104. */
    105. transient Node<K, V>[] table;
    106. /**
    107. * hashMap中存储的数量
    108. */
    109. transient int size;
    110. /**
    111. * 修改次数,主要用于快速失败机制
    112. */
    113. transient int modCount;
    114. /**
    115. * 扩容阈值=容量*负载因子,size到达该值时需要扩容
    116. */
    117. int threshold;
    118. /**
    119. * 负载因子
    120. */
    121. final float loadFactor;
    122. /**
    123. * 构造方法
    124. *
    125. * @param initialCapacity 初始容量
    126. * @param loadFactor 负载因子
    127. */
    128. public MyHashMap(int initialCapacity, float loadFactor) {
    129. if (initialCapacity < 0)
    130. throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
    131. if (initialCapacity > MAXIMUM_CAPACITY)
    132. initialCapacity = MAXIMUM_CAPACITY;
    133. if (loadFactor <= 0 || Float.isNaN(loadFactor))
    134. throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
    135. this.loadFactor = loadFactor;
    136. this.threshold = tableSizeFor(initialCapacity);
    137. }
    138. /**
    139. * 使用默认负载因子的构造方法
    140. *
    141. * @param initialCapacity 初始容量
    142. */
    143. public MyHashMap(int initialCapacity) {
    144. this(initialCapacity, DEFAULT_LOAD_FACTOR);
    145. }
    146. /**
    147. * 使用默认的初始容量和负载因子
    148. */
    149. public MyHashMap() {
    150. this.loadFactor = DEFAULT_LOAD_FACTOR;
    151. }
    152. public int size() {
    153. return size;
    154. }
    155. public boolean isEmpty() {
    156. return size == 0;
    157. }
    158. /**
    159. * 根据key获取value
    160. *
    161. * @param key
    162. * @return
    163. */
    164. public V get(Object key) {
    165. Node<K, V> e;
    166. // 计算key的hash, 通过getNode方法获取key所在的节点
    167. return (e = getNode(hash(key), key)) == null ? null : e.value;
    168. }
    169. final Node<K, V> getNode(int hash, Object key) {
    170. /**
    171. * 几个字段的含义
    172. * tab 存储Node的数组
    173. * first 当前key的hash 所在的的链表 的 首个节点
    174. * e 当first不是的时候, 用e来遍历
    175. * n 当前table的legth, 用于计算当前key所在的index, 通过(n - 1) & hash
    176. * k 此次方法中的key
    177. */
    178. Node<K, V>[] tab;
    179. Node<K, V> first, e;
    180. int n;
    181. K k;
    182. // 判断table是否为空 && 判断table长度是否大于0 && 判断当前key所在的index是否为空(即该index下的链表是否为空)
    183. if ((tab = table) != null && (n = tab.length) > 0 &&
    184. (first = tab[(n - 1) & hash]) != null) {
    185. // 判断链表的头结点是不是当前查询的节点,是的话直接返回,每次查询都会走该逻辑
    186. if (first.hash == hash &&
    187. ((k = first.key) == key || (key != null && key.equals(k))))
    188. return first;
    189. // 头结点不是,所以需要遍历链表,或遍历树 查询
    190. if ((e = first.next) != null) {
    191. // TODO 树的逻辑先省略
    192. // if (first instanceof TreeNode)
    193. // return ((TreeNode<K,V>)first).getTreeNode(hash, key);
    194. do {
    195. if (e.hash == hash &&
    196. ((k = e.key) == key || (key != null && key.equals(k))))
    197. return e;
    198. } while ((e = e.next) != null);
    199. }
    200. }
    201. return null;
    202. }
    203. /**
    204. * 判断hashMap中是否存在该key
    205. *
    206. * @param key key
    207. * @return 是否在当前hashMap中
    208. */
    209. public boolean containKey(Object key) {
    210. return getNode(hash(key), key) != null;
    211. }
    212. public V put(K key, V value) {
    213. return putVal(hash(key), key, value, false, true);
    214. }
    215. /**
    216. * @param hash 当前key的hash值
    217. * @param key key
    218. * @param value value
    219. * @param onlyIfAbsent 仅在不存在时put,存在时不修改值
    220. * @param evict 这里没啥用
    221. * @return 老的值,没有则为空
    222. */
    223. final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
    224. boolean evict) {
    225. Node<K, V>[] tab;
    226. Node<K, V> p;
    227. // n表示table的长度,用于计算index;
    228. // i表示当前的index
    229. int n, i;
    230. // 如果table为空或者长度为0, 说明table没有初始化,此处开始初始化
    231. if ((tab = table) == null || (n = tab.length) == 0)
    232. n = (tab = resize()).length;
    233. // 如果当前key的hash所在的链表为空, 则直接新建, 然后设置
    234. if ((p = tab[i = (n - 1) & hash]) == null)
    235. tab[i] = newNode(hash, key, value, null);
    236. // 到达这个else, 说明链表不为空
    237. else {
    238. // e最终表示查询到的节点
    239. Node<K, V> e;
    240. K k;
    241. // 此时p是链表的头节点, 如果此时与当前key相等, 则表示查到了
    242. if (p.hash == hash &&
    243. ((k = p.key) == key || (key != null && key.equals(k))))
    244. e = p;
    245. // TODO 头结点是树节点的情况
    246. // else if (p instanceof TreeNode)
    247. // e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
    248. // 往链表里插入
    249. else {
    250. // 遍历链表
    251. for (int binCount = 0; ; ++binCount) {
    252. // 遍历到末尾还是不存在, 则新建一个节点挂到链表后面, 如果到达树化阈值了, 则进行树化
    253. if ((e = p.next) == null) {
    254. p.next = newNode(hash, key, value, null);
    255. if (binCount >= TREEIFY_THRESHOLD - 1) {
    256. // TODO 树化
    257. // treeifyBin(tab, hash);
    258. }
    259. break;
    260. }
    261. // 遍历的时候找到, 则退出循环, 此时e为当前key的节点
    262. if (e.hash == hash &&
    263. ((k = e.key) == key || (key != null && key.equals(k))))
    264. break;
    265. p = e;
    266. }
    267. }
    268. // e!=null 说明该key之前就存在, 则此时需要通过onlyIfAbsent决定是不是需要设置值。
    269. // 不管设不设置都会返回旧值
    270. if (e != null) { // existing mapping for key
    271. V oldValue = e.value;
    272. if (!onlyIfAbsent || oldValue == null)
    273. e.value = value;
    274. afterNodeAccess(e);
    275. return oldValue;
    276. }
    277. }
    278. // 增加modCount, 为了快速失败处理
    279. ++modCount;
    280. // 如果数量已经到达 容量*负载因子的大小,则需要扩容
    281. if (++size > threshold)
    282. resize();
    283. afterNodeInsertion(evict);
    284. return null;
    285. }
    286. void afterNodeAccess(Node<K, V> p) {
    287. }
    288. void afterNodeInsertion(boolean evict) {
    289. }
    290. void afterNodeRemoval(Node<K, V> p) {
    291. }
    292. Node<K, V> newNode(int hash, K key, V value, Node<K, V> next) {
    293. return new Node<>(hash, key, value, next);
    294. }
    295. /**
    296. * 扩容
    297. *
    298. * @return 扩容后的数组
    299. */
    300. final Node<K, V>[] resize() {
    301. // 老的table、容量、扩容阈值(到达该值需要扩容)
    302. Node<K, V>[] oldTab = this.table;
    303. int oldCap = (oldTab == null) ? 0 : oldTab.length;
    304. int oldThr = this.threshold;
    305. int newCap, newThr = 0;
    306. if (oldCap > 0) {
    307. // 扩容不了了, 最大了
    308. if (oldCap >= MAXIMUM_CAPACITY) {
    309. threshold = Integer.MAX_VALUE;
    310. return oldTab;
    311. }
    312. // 扩容一倍
    313. else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
    314. oldCap >= DEFAULT_INITIAL_CAPACITY)
    315. newThr = oldThr << 1; // double threshold
    316. }
    317. // 初始化
    318. // 该if出现的情况: 创建map时指定了容量(所以threshold会有值), 但是table还未初始化
    319. else if (oldThr > 0) // initial capacity was placed in threshold
    320. newCap = oldThr;
    321. // 该if出现的情况:创建map时没传参数
    322. else { // zero initial threshold signifies using defaults
    323. newCap = DEFAULT_INITIAL_CAPACITY;
    324. newThr = (int) (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
    325. }
    326. // 对应上面的else if (oldThr > 0)的情况
    327. if (newThr == 0) {
    328. float ft = (float) newCap * loadFactor;
    329. newThr = (newCap < MAXIMUM_CAPACITY && ft < (float) MAXIMUM_CAPACITY ?
    330. (int) ft : Integer.MAX_VALUE);
    331. }
    332. // 设置新的扩容阈值, 创建新的数组
    333. threshold = newThr;
    334. Node<K, V>[] newTab = (Node<K, V>[]) new Node[newCap];
    335. table = newTab;
    336. // 如果老的table不为空, 则需要把里面的内容移到新的table
    337. if (oldTab != null) {
    338. // 遍历数组
    339. for (int j = 0; j < oldCap; ++j) {
    340. Node<K, V> e;
    341. // 如果当前链表不为空
    342. if ((e = oldTab[j]) != null) {
    343. oldTab[j] = null;
    344. // e.next == null 说明链表只有一个节点
    345. if (e.next == null)
    346. // 直接丢到新的table里去
    347. newTab[e.hash & (newCap - 1)] = e;
    348. // TODO 树化
    349. // else if (e instanceof TreeNode)
    350. // ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
    351. // 此处说明是链表, 且有多个节点
    352. else { // preserve order
    353. Node<K, V> loHead = null, loTail = null;
    354. Node<K, V> hiHead = null, hiTail = null;
    355. Node<K, V> next;
    356. /**
    357. *遍历链表, 根据e.hash & oldCap判断是应该挂在哪个链表
    358. * ==0 挂在原先index位置的链表
    359. * !=0 挂在原先index+oldCap位置的链表
    360. * why ->
    361. * oldCar是2的指数值, 说明二进制只有一个1(比如8 -> 1000), (e.hash & oldCap) == 0说明hash对应oldCar为1的那一位为0(比如...xxxx0xxx)
    362. * 扩容后的容量为2oldCar, 计算index时使用 (2oldCap - 1) & hash, 与 (oldCar - 1) & hash 结果相等,
    363. * 因为2oldCap - 1 与 oldCar - 1 在二进制上的区别就是前者多了一个1, 但是e.hash的那一位为0
    364. * 比如原容量 = 8 -> 1000, 新容量 = 16 -> 10000,
    365. * (e.hash & oldCap) == 0 -> 说明e.hash的倒数第四位为0, 即 ...xxxx0xxx;
    366. * 2oldCap - 1 -> 01111 ; oldCar - 1 -> 0111, 两者就差倒数第四位的1, 但是该1不会影响index的计算, 因为e.hash的倒数第四位为0
    367. * (e.hash & oldCap) != 0 -> 说明e.hash的倒数第四位为1, 即 ...xxxx1xxx;
    368. * 2oldCap - 1 -> 01111 ; oldCar - 1 -> 0111, index的计算结果, 前者比后者大倒数第四位的1, 即oldCar
    369. */
    370. do {
    371. next = e.next;
    372. if ((e.hash & oldCap) == 0) {
    373. if (loTail == null)
    374. loHead = e;
    375. else
    376. loTail.next = e;
    377. loTail = e;
    378. } else {
    379. if (hiTail == null)
    380. hiHead = e;
    381. else
    382. hiTail.next = e;
    383. hiTail = e;
    384. }
    385. } while ((e = next) != null);
    386. // 挂到新的table下
    387. if (loTail != null) {
    388. loTail.next = null;
    389. newTab[j] = loHead;
    390. }
    391. if (hiTail != null) {
    392. hiTail.next = null;
    393. newTab[j + oldCap] = hiHead;
    394. }
    395. }
    396. }
    397. }
    398. }
    399. return newTab;
    400. }
    401. public V remove(Object key) {
    402. Node<K, V> e;
    403. return (e = removeNode(hash(key), key, null, false, true)) == null ?
    404. null : e.value;
    405. }
    406. /**
    407. * 移除节点
    408. *
    409. * @param hash hash for key
    410. * @param key the key
    411. * @param value the value to match if matchValue, else ignored
    412. * @param matchValue ture -> 只有在value相等时才移除
    413. * @param movable 树节点使用字段,此处不关注
    414. * @return 不存在该节点则返回null,否则返回该节点
    415. */
    416. final Node<K, V> removeNode(int hash, Object key, Object value,
    417. boolean matchValue, boolean movable) {
    418. Node<K, V>[] tab;
    419. Node<K, V> p;
    420. int n, index;
    421. // 判断table是否空 & hash所在index是否空
    422. if ((tab = table) != null && (n = tab.length) > 0 &&
    423. (p = tab[index = (n - 1) & hash]) != null) {
    424. Node<K, V> node = null, e;
    425. K k;
    426. V v;
    427. // 判断链表头结点是不是
    428. if (p.hash == hash &&
    429. ((k = p.key) == key || (key != null && key.equals(k))))
    430. node = p;
    431. else if ((e = p.next) != null) {
    432. // if (p instanceof TreeNode)
    433. // node = ((TreeNode<K,V>)p).getTreeNode(hash, key);
    434. // 遍历寻找
    435. // else
    436. {
    437. do {
    438. if (e.hash == hash &&
    439. ((k = e.key) == key ||
    440. (key != null && key.equals(k)))) {
    441. node = e;
    442. break;
    443. }
    444. p = e;
    445. } while ((e = e.next) != null);
    446. }
    447. }
    448. // 找到节点 && (不需要匹配value || value相等)
    449. if (node != null && (!matchValue || (v = node.value) == value ||
    450. (value != null && value.equals(v)))) {
    451. // if (node instanceof TreeNode)
    452. // ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);
    453. // else
    454. if (node == p)
    455. tab[index] = node.next;
    456. else
    457. p.next = node.next;
    458. ++modCount;
    459. --size;
    460. afterNodeRemoval(node);
    461. return node;
    462. }
    463. }
    464. return null;
    465. }
    466. }