Map

Map stores values behind keys. That said, values in a map can be obtained using a key.

Lets create very simple hash map. This hash map is fixed size and does not count other types than integer.

class MyHashMap {

    Integer[] values = new Integer[1000000];

    /** Initialize your data structure here. */
    public MyHashMap() {
    }

    /** value will always be positive. */
    public void put(int key, int value) {
        values[hash(key)] = value;
    }

    /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
    public int get(int key) {
        Integer result = values[hash(key)];
        if (result == null) {
            return -1;
        }
        return result;
    }

    /** Removes the mapping of the specified value key if this map contains a mapping for the key */
    public void remove(int key) {
        values[hash(key)] = null;
    }

    private int hash(int value) {
        return values.length % value;
        // or we can use bit operator to limit number to upper boundary, which is length of array
        // return hashCode & (entries.length - 1);
        // hashCode: 10 , n: 9
        // hashCode (in binary): 1010 , n (in binary): 1001
        // position (in binary): 1000 (8 in decimal)
    }
}

Now we can use the hash map as follows.

MyHashMap hashMap = new MyHashMap();
hashMap.put(1, 1);          
hashMap.put(2, 2);         
hashMap.get(1);            // returns 1
hashMap.get(3);            // returns -1 (not found)
hashMap.put(2, 1);          // update the existing value
hashMap.get(2);            // returns 1 
hashMap.remove(2);          // remove the mapping for 2
hashMap.get(2);            // returns -1 (not found)

Implementation using Entry

We need to use Entry class to handle duplicates (when two objects have the same hash code but they are not equal).

class HashMap<K, V> {
    private Entry[] entries;

    HashMap() {
        entries = new Entry[10];
    }

    public void put(K key, V value) {
        Entry<K, V> entry = new Entry<>(key, value);
        int position = calculateHashCode(key);
        if (entries[position] == null) {
            entries[position] = entry;
        } else {
            Entry<K, V> available = findNextAvailableEntry(position);
            available.next = entry;
        }
    }

    public V get(K key) {
        int position = calculateHashCode(key);
        Entry entry = entries[position];
        while (!entry.key.equals(key)) {
            entry = entry.next;
        }
        return (V) entry.value;
    }

    Entry<K, V> findNextAvailableEntry(int position) {
        Entry<K, V> current = entries[position];
        if (current.next != null) {
            current = current.next;
        }
        return current;
    }

    int calculateHashCode(K key) {
        return key.hashCode() % entries.length;
    }

    class Entry<K, V> {
        K key;
        V value;
        Entry<K, V> next; // linked list

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

Lets try to use the hash map.

public class Test {

    public static void main(String... args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("a", 1);
        map.put("b", 2);
        map.put("k", 3); // k has conflicting position 

        Integer one = map.get("a");
        System.out.println(one);

        Integer three = map.get("k");
        System.out.println(three);

        System.out.println("a: " + map.calculateHashCode("a"));
        System.out.println("b: " + map.calculateHashCode("b"));
        System.out.println("c: " + map.calculateHashCode("c"));
        System.out.println("d: " + map.calculateHashCode("d"));
        System.out.println("e: " + map.calculateHashCode("e"));
        System.out.println("f: " + map.calculateHashCode("f"));
        System.out.println("g: " + map.calculateHashCode("g"));
        System.out.println("h: " + map.calculateHashCode("h"));
        System.out.println("i: " + map.calculateHashCode("i"));
        System.out.println("j: " + map.calculateHashCode("j"));
        System.out.println("k: " + map.calculateHashCode("k"));
    }
}

How the position is calculated.

println "a".hashCode()
println "b".hashCode()
println "k".hashCode()
println "u".hashCode()

println "a".hashCode() % 10
println "k".hashCode() % 10
println "u".hashCode() % 10

Here is the output.

97
98
107
117

7
7
7

Last updated