Cinco, tabla hash
1. Concepto
Una tabla hash es una estructura de datos con una relación de mapeo, es decir, dada una CLAVE, se puede encontrar el VALOR correspondiente. CLAVE y VALOR forman una Entrada (o Nodo)
KEY es única. Si la entrada agregada más tarde es igual a la CLAVE de una entrada anterior, solo el nuevo VALOR sobrescribirá el antiguo VALOR y no se creará una nueva entrada
Para mantener todas las entradas, puede usar la estructura de matriz. Al mismo tiempo, para reducir la ocupación 连续的内存空间
, puede usar la estructura de lista enlazada individualmente para mantener la Entrada correspondiente a la CLAVE del mismo valor hashCode (en Para mejorar mejor el rendimiento, también puede cambiar la conversión individual a una lista vinculada a un árbol binario, o restaurar un árbol binario a una lista vinculada individualmente)
2. Métodos comunes
- put agrega el elemento a la tabla hash (tenga en cuenta que la entrada de la CLAVE igual, el nuevo VALOR sobrescribirá el antiguo VALOR)
- obtener Encuentra el VALOR correspondiente de acuerdo con la CLAVE dada
- remove Elimina la entrada correspondiente de acuerdo con la CLAVE dada
3. Ejemplo
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) + '}';
}
}