1.什么是哈希表

哈希表是联合哈希算法联合其余数据结构形成的一种数据结构。

为什么会产生这样的数据结构呢?

次要起因是在现实状况下,取出和放入元素所耗费的工夫复杂度为

\( O(1) \)

比方咱们看一种常见的实现形式,哈希算法+数组+链表形成的哈希表:

假如数组index从1开始,那么依据哈希算法,元素1就放在数组下标为1的中央,元素3就放在数组下标为3的中央,元素5放在数组下标为1的中央,然而因为元素1曾经在数组中了,对于这种状况,咱们的一种解决形式就是元素1和元素5通过链表连贯,元素1依然在数组中,新退出的元素5放在元素1前面,元素1的next节点指向元素5.

2. java实现

哈希表的用处很广,比方java的HashMap、HashSet。

对于哈希表,咱们的操作次要是PUT和GET操作。

上面就来看看怎么实现繁难版本的HashMap。

import java.util.Arrays;import java.util.Objects;/** * key and value are not permitted null * @author bennetty74 * @since 2021.10.24 */public class HashMap <K,V> implements Map<K,V>{    // 申明一个ENTRY数组用于寄存元素    private Entry<K,V>[] entries;    private final double loadFactor = 0.75d;    private int capacity = 8;    private int size = 0;    @SuppressWarnings("unchecked")    public HashMap() {        entries = new Entry[this.capacity];    }    @SuppressWarnings("unchecked")    public HashMap(int capacity) {        this.capacity = capacity;        entries = new Entry[capacity];    }    @Override    public boolean contains(K key) {        int idx = getIndex(key);        if (entries[idx] == null) {            return false;        }        Entry<K, V> entry = entries[idx];        while (entry != null) {            if (entry.key.equals(key)) {                return true;            }            entry = entry.next;        }        return false;    }    // put操作,不容许key和value为null    public boolean put(K key, V value) {        if (Objects.isNull(key) || Objects.isNull(value)) {            throw new IllegalArgumentException("Key or value is null");        }        int idx = getIndex(key);        // if null, put in entries array        if (Objects.isNull(entries[idx])) {            entries[idx] = new Entry<>(key, value);        } else {            // else put at the head of Entry list            Entry<K, V> newEntry = new Entry<>(key, value);            newEntry.next = entries[idx];            entries[idx] = newEntry;        }        // if load factor greater than 0.75, then rehash        if (size++ / (double) capacity > 0.75f) {            rehash();        }        return true;    }    private void rehash() {        capacity = 2 * capacity;        Entry<K, V>[] oldEntries = Arrays.copyOf(this.entries, capacity);        entries = new Entry[capacity];        for (Entry<K, V> oldEntry : oldEntries) {            if (oldEntry != null) {                put(oldEntry.key, oldEntry.value);            }        }    }    public V get(K key) {        if (Objects.isNull(key)) {            throw new IllegalArgumentException("Key is null");        }        // get idx by key's hashCode        int idx = getIndex(key);        Entry<K, V> entry = entries[idx];        if (!Objects.isNull(entry)) {            while (!Objects.isNull(entry)) {                if (key.equals(entry.key)) {                    return entry.value;                }                entry = entry.next;            }        }        // not found the specific key, return null        return null;    }    // 此处的hash算法很简略,就是依据key的hashCode除以entry数组的容量的余数作为数组下标寄存元素    private int getIndex(K key) {        return key.hashCode() % capacity;    }    @Override    public String toString() {        StringBuilder sb = new StringBuilder();        sb.append("HashMap { ");        for (int i = 0; i < capacity; i++) {            if (entries[i] != null) {                Entry<K, V> entry = entries[i];                while (entry != null) {                    sb.append(entry.key).append("=").append(entry.value).append(",");                    entry = entry.next;                }            }        }        sb.replace(sb.length() - 1, sb.length(), "").append(" }");        return sb.toString();    }    // Entry类,蕴含HashMap的key和value    private static class Entry<K,V> {        K key;        V value;        public Entry(K key, V value) {            this.key = key;            this.value = value;        }        Entry<K,V> next;    }}