Implement a HashMap manually

Keywords: Java

Overview of implementing a HashMap manually

  after reading the HashMap source code, in order to deepen the understanding of the source code, a simple HashMap is implemented manually. The HashMap implemented by ourselves only implements the put,get value methods and resize() methods of the HashMap, so as to realize the capacity expansion

Define data store entity Entry

Customize an Entry and override the hashCode and equals methods. This implementation comes from the original HashMap

package base;

import java.util.Objects;

/**
  * @time: Created in 23:03 2018/1/2
 * @desc Storage entity Entry class
 */
public class Entry<K, V> {

    int hash;
    K key;
    V value;
    Entry<K, V> next;

    public Entry() {
    }

    public Entry(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public Entry(int hash, K key, V value, Entry<K, V> next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }

    public K getKey() {
        return key;
    }

    public void setKey(K key) {
        this.key = key;
    }

    public V getValue() {
        return value;
    }

    public void setValue(V value) {
        this.value = value;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o instanceof Entry) {
            Entry<K, V> e = (Entry<K, V>) o;
            if (Objects.equals(e.key, key) &&
                    Objects.equals(e.value, value)) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(key) ^ Objects.hash(value);
    }

    @Override
    public String toString() {
        return key + "=" + value;
    }
}

Implement HashMap manually

The HashMap is implemented manually, the data is stored in the linear hash table, the put and get methods are implemented, the hash value is calculated according to the key, and the resize method is implemented. The source code is as follows:

package base;

/**
 * @time: Created in 22:43 2018/1/2
 * @desc A simplified version of HashMap implemented manually only supports put,get value and resize functions
 */
public class HashMap<K, V> {

    //Initial capacity of hash table
    static final int initial_capacity = 4;
    //Factor loaded
    float load_factor = 0.75f;
    //Record the number of entries
    int count = 0;

    Entry<K, V>[] table;


    public K put(K key, V value) {
        Entry<K, V> newEntry = new Entry(key, value);
        int hash = hash(key);
        if (table == null) {
            table = new Entry[initial_capacity];
            count++;
        }
        Entry<K, V> head = table[hash];
        //Perform capacity expansion,
        if (count > initial_capacity * load_factor) {
            resize();
        }
        if (head == null) {
            table[hash] = newEntry;
            count++;
            return key;
        } else {
            Entry tail = new Entry<K, V>();
            if (head.next == null) {
                head.next = newEntry;
            } else {
                do {
                    tail = head;
                } while ((head = head.next) != null);
                tail.next = newEntry;
            }
            count++;
            return key;
        }
    }

    public V get(K key) {
        Entry<K, V> entry;
        return (entry = getEntry(hash(key), key)) == null ? null : entry.value;
    }

    public Entry<K, V> getEntry(int hash, K key) {
        Entry<K, V> entry = table[hash];
        if (entry == null) {
            return null;
        } else if (entry != null && entry.next == null) {
            return entry;
        } else if (entry.next != null) {
            do {
                if (hash == hash(entry.key) &&
                        (key == entry.key || (key != null && key.equals(entry.key)))) {
                    return entry;
                }
            } while ((entry = entry.next) != null);
            return entry;
        }
        return null;
    }

    public int resize() {
        int newCapacity = initial_capacity << 2;
        Entry[] newTable = new Entry[newCapacity];
        System.arraycopy(table, 0, newTable, 0, table.length);
        this.table = newTable;
        return newCapacity;
    }

    public final int hash(K key) {
        //The key.hashCode may generate a negative value. Perform the key.hashCode() & 0x7fffff operation once,
        //Change to integer, and generate hash value direct module 4 here to ensure that the generated hash value will not change due to capacity expansion
        return (key == null) ? 0 : (key.hashCode() & 0x7FFFFFFF % initial_capacity);
    }

    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<>();
        map.put("name1", "Yan Song");
        map.put("name2", "Gao Gong");
        map.put("name3", "Xu Jie");
        map.put("name4", "Zhang Juzheng");
        map.put("name5", "Shenshihang");
        System.out.println("map Current capacity:" + map.count);
        System.out.println(map.get("name1"));
        System.out.println(map.get("name5"));
    }
}

The HashMap data storage stack is as follows:

The output results are as follows:

map current capacity: 6
 Yan Song
 Shenshihang

Posted by shan_cool on Mon, 04 May 2020 12:49:33 -0700