五、哈希表
1、概念
哈希表是一种存在映射关系的数据结构,即给定一个KEY,可以找到对应的VALUE,KEY和VALUE组成了一个Entry(或Node)
KEY是唯一的。如果后添加的Entry和之前的某个Entry的KEY相等,则只会将新的VALUE覆盖旧的VALUE,而不会创建新的Entry
为了维护所有的Entry,可以使用数组结构,同时为了少占用连续的内存空间
,可以将相同 hashCode 值的KEY所对应的Entry,使用单向链表结构维护起来(为了更好地提升性能,还可以将满足条件的单向链表转换为二叉树,或将二叉树还原成为单向链表)
2、常用方法
- put 添加元素到哈希表中(注意相等的KEY的Entry,其新的VALUE会覆盖旧的VALUE)
- get 根据给定的KEY,找到对应的VALUE
- remove 根据给定的KEY,移除对应的Entry
3、示例
class HashTable<K, V> {
private Entry<K, V>[] table;
private final int length;
private int size;
public HashTable(int length) {
this.length = length;
this.size = 0;
}
public void put(K key, V value) {
if (null == key || null == value) {
throw new NullPointerException();
}
if (null == table) {
@SuppressWarnings("unchecked")
Entry<K, V>[] table = (Entry<K, V>[])new Entry[this.length];
this.table = table;
}
int hash = hash(key);
Entry<K, V> entry = table[hash];
while (null != entry) {
if (entry.key.equals(key)) {
entry.value = value;
return;
}
entry = entry.prev;
}
entry = table[hash];
Entry<K, V> put = new Entry<K, V>(key, value);
table[hash] = put;
put.prev = entry;
this.size++;
}
public V get(K key) {
if (null == key) {
throw new NullPointerException();
}
int hash = hash(key);
Entry<K, V> entry = table[hash];
while (null != entry) {
if (entry.key.equals(key)) {
return entry.value;
}
entry = entry.prev;
}
return null;
}
public boolean remove(K key) {
if (null == key) {
throw new NullPointerException();
}
int hash = hash(key);
Entry<K, V> entry = table[hash];
boolean first = true;
Entry<K, V> next = table[hash];
while (null != entry) {
if (entry.key.equals(key)) {
if (first) {
table[hash] = entry.prev;
} else {
next.prev = entry.prev;
}
this.size--;
return true;
}
entry = entry.prev;
if (first) {
first = false;
} else {
next = next.prev;
}
}
return false;
}
public int size() {
return this.size;
}
private int hash(K key) {
return key.hashCode() % this.length;
}
private static class Entry<K, V> {
private final K key;
private V value;
private Entry<K, V> prev;
private Entry(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public String toString() {
return this.key + "=" + this.value;
}
}
@Override
public String toString() {
if (null == table) {
return "{}";
}
StringBuilder sBuilder = new StringBuilder("{");
for (int i = 0; i < this.length; i++) {
Entry<K, V> entry = table[i];
while (null != entry) {
sBuilder.append(entry.toString()).append(',').append(' ');
entry = entry.prev;
}
}
return sBuilder.substring(0, sBuilder.length() - 2) + '}';
}
}