实现

点我查看完整代码 :) 🚀🚀🚀
这里采用的是固定table容量的实现,主要用于感受 hash冲突 对于性能的影响
如果容量是8,put10万次和容量是1008,put10w次的速度不是一个量级的,主要还是链表对于性能的影响

  1. package io.github.chenshun00.data.hash;
  2. import java.util.Objects;
  3. /**
  4. * 简单hash实现,一个固定数组+链表实现,不进行 <strong>rehash</strong>
  5. *
  6. * @author chenshun00@gmail.com
  7. * @since 2021/9/4 4:49 下午
  8. */
  9. public class SimpleHashImpl<K, V> implements Hash<K, V> {
  10. public Node<K, V>[] tables;
  11. private int size;
  12. @SuppressWarnings("unchecked")
  13. public SimpleHashImpl(int capacity) {
  14. this.tables = new Node[capacity];
  15. }
  16. @Override
  17. public V put(K key, V value) {
  18. check(key, value);
  19. final int hash = hash(key);
  20. final int index = hash & (tables.length - 1);
  21. Node<K, V> head = tables[index];
  22. if (head == null) {
  23. final Node<K, V> kvNode = new Node<>(key, value, null);
  24. tables[index] = kvNode;
  25. } else {
  26. if (head.k.equals(key)) {
  27. final V v = head.v;
  28. head.v = value;
  29. return v;
  30. }
  31. while (head.next != null) {
  32. head = head.next;
  33. final K k = head.k;
  34. if (k.equals(key)) {
  35. final V v = head.v;
  36. head.v = value;
  37. return v;
  38. }
  39. }
  40. head.next = new Node<>(key, value, null);
  41. }
  42. incr();
  43. return null;
  44. }
  45. @Override
  46. public V get(K key) {
  47. Objects.requireNonNull(key, "key can't be null");
  48. final int hash = hash(key);
  49. final int index = hash & (tables.length - 1);
  50. Node<K, V> head = tables[index];
  51. if (head == null) {
  52. return null;
  53. }
  54. if (head.k.equals(key)) {
  55. return head.v;
  56. }
  57. head = head.next;
  58. do {
  59. if (head.k.equals(key)) {
  60. return head.v;
  61. }
  62. head = head.next;
  63. } while (head.next != null);
  64. return null;
  65. }
  66. @Override
  67. public V remove(K key) {
  68. Objects.requireNonNull(key, "key can't be null");
  69. final int hash = hash(key);
  70. final int index = hash & (tables.length - 1);
  71. Node<K, V> head = tables[index];
  72. if (head == null) {
  73. return null;
  74. }
  75. if (head.k.equals(key)) {
  76. if (head.next == null) {
  77. tables[index] = null;
  78. } else {
  79. tables[index] = head.next;
  80. }
  81. decr();
  82. return head.v;
  83. }
  84. Node<K, V> leader = head;
  85. head = head.next;
  86. do {
  87. if (head.k.equals(key)) {
  88. leader.next = head.next;
  89. decr();
  90. return head.v;
  91. }
  92. leader = head;
  93. head = head.next;
  94. } while (head.next != null);
  95. return null;
  96. }
  97. @Override
  98. public int size() {
  99. return size;
  100. }
  101. private void incr() {
  102. size++;
  103. }
  104. private void decr() {
  105. size--;
  106. }
  107. }

测试代码

  1. public class SimpleHashImplTest {
  2. //可以感受到hash冲突对于put性能的严重影响
  3. //如果容量是8,put10万次和容量是1008,put10w次的速度不是一个量级的,主要还是链表对于性能的影响
  4. private final Hash<String, String> simple = new SimpleHashImpl<>(1008);
  5. @Test
  6. public void put() {
  7. String put = simple.put("first", "first");
  8. Assert.assertNull(put);
  9. Assert.assertEquals(1, simple.size());
  10. put = simple.put("first", "reFirst");
  11. Assert.assertNotNull(put);
  12. Assert.assertEquals(1, simple.size());
  13. for (int i = 0; i < 100000; i++) {
  14. simple.put("first" + i, "first" + i);
  15. }
  16. Assert.assertEquals(100001, simple.size());
  17. Assert.assertEquals("first88", simple.get("first88"));
  18. final String first88 = simple.remove("first88");
  19. Assert.assertEquals("first88", first88);
  20. Assert.assertEquals(100000, simple.size());
  21. }
  22. }