实现
点我查看完整代码 :) 🚀🚀🚀
这里采用的是固定table容量的实现,主要用于感受 hash冲突
对于性能的影响
如果容量是8,put10万次和容量是1008,put10w次的速度不是一个量级的,主要还是链表对于性能的影响
package io.github.chenshun00.data.hash;
import java.util.Objects;
/**
* 简单hash实现,一个固定数组+链表实现,不进行 <strong>rehash</strong>
*
* @author chenshun00@gmail.com
* @since 2021/9/4 4:49 下午
*/
public class SimpleHashImpl<K, V> implements Hash<K, V> {
public Node<K, V>[] tables;
private int size;
@SuppressWarnings("unchecked")
public SimpleHashImpl(int capacity) {
this.tables = new Node[capacity];
}
@Override
public V put(K key, V value) {
check(key, value);
final int hash = hash(key);
final int index = hash & (tables.length - 1);
Node<K, V> head = tables[index];
if (head == null) {
final Node<K, V> kvNode = new Node<>(key, value, null);
tables[index] = kvNode;
} else {
if (head.k.equals(key)) {
final V v = head.v;
head.v = value;
return v;
}
while (head.next != null) {
head = head.next;
final K k = head.k;
if (k.equals(key)) {
final V v = head.v;
head.v = value;
return v;
}
}
head.next = new Node<>(key, value, null);
}
incr();
return null;
}
@Override
public V get(K key) {
Objects.requireNonNull(key, "key can't be null");
final int hash = hash(key);
final int index = hash & (tables.length - 1);
Node<K, V> head = tables[index];
if (head == null) {
return null;
}
if (head.k.equals(key)) {
return head.v;
}
head = head.next;
do {
if (head.k.equals(key)) {
return head.v;
}
head = head.next;
} while (head.next != null);
return null;
}
@Override
public V remove(K key) {
Objects.requireNonNull(key, "key can't be null");
final int hash = hash(key);
final int index = hash & (tables.length - 1);
Node<K, V> head = tables[index];
if (head == null) {
return null;
}
if (head.k.equals(key)) {
if (head.next == null) {
tables[index] = null;
} else {
tables[index] = head.next;
}
decr();
return head.v;
}
Node<K, V> leader = head;
head = head.next;
do {
if (head.k.equals(key)) {
leader.next = head.next;
decr();
return head.v;
}
leader = head;
head = head.next;
} while (head.next != null);
return null;
}
@Override
public int size() {
return size;
}
private void incr() {
size++;
}
private void decr() {
size--;
}
}
测试代码
public class SimpleHashImplTest {
//可以感受到hash冲突对于put性能的严重影响
//如果容量是8,put10万次和容量是1008,put10w次的速度不是一个量级的,主要还是链表对于性能的影响
private final Hash<String, String> simple = new SimpleHashImpl<>(1008);
@Test
public void put() {
String put = simple.put("first", "first");
Assert.assertNull(put);
Assert.assertEquals(1, simple.size());
put = simple.put("first", "reFirst");
Assert.assertNotNull(put);
Assert.assertEquals(1, simple.size());
for (int i = 0; i < 100000; i++) {
simple.put("first" + i, "first" + i);
}
Assert.assertEquals(100001, simple.size());
Assert.assertEquals("first88", simple.get("first88"));
final String first88 = simple.remove("first88");
Assert.assertEquals("first88", first88);
Assert.assertEquals(100000, simple.size());
}
}