Data structures

datastructures6HashTableImpl

Path
pkg3datastructures/datastructures6HashTableImpl.java
Package
pkg3datastructures
Study order
6
Run
Single-file source launch
Command
java pkg3datastructures/datastructures6HashTableImpl.java
Lesson
Back to the chapter

There is no in-browser runner. This is the file from the curriculum, unchanged.

pkg3datastructures/datastructures6HashTableImpl.java
1package pkg3datastructures;2 3/*4 * datastructures6HashTableImpl.java5 * ------------------6 * A hash map using separate chaining (buckets of linked entries) with resizing.7 * Demonstrates how HashMap works under the hood.8 *9 * COMPLEXITY: get/put/remove O(1) average, O(n) worst (all collisions).10 * KEY IDEAS: hashCode -> bucket index; load factor triggers resize/rehash.11 */12public class datastructures6HashTableImpl {13 14    static class Entry<K, V> {15        final K key; V value; Entry<K, V> next;16        Entry(K key, V value) { this.key = key; this.value = value; }17    }18 19    static class MyHashMap<K, V> {20        private Entry<K, V>[] buckets;21        private int size;22        private static final double LOAD_FACTOR = 0.75;23 24        @SuppressWarnings("unchecked")25        MyHashMap() { buckets = new Entry[8]; }26 27        private int indexFor(K key) {28            int h = (key == null) ? 0 : key.hashCode();29            h ^= (h >>> 16);                       // spread bits (like HashMap)30            return (buckets.length - 1) & h;       // fast modulo for power-of-two size31        }32 33        void put(K key, V value) {34            int i = indexFor(key);35            for (Entry<K, V> e = buckets[i]; e != null; e = e.next) {36                if (java.util.Objects.equals(e.key, key)) { e.value = value; return; }37            }38            Entry<K, V> head = new Entry<>(key, value);39            head.next = buckets[i];40            buckets[i] = head;41            if (++size > buckets.length * LOAD_FACTOR) resize();42        }43 44        V get(K key) {45            for (Entry<K, V> e = buckets[indexFor(key)]; e != null; e = e.next) {46                if (java.util.Objects.equals(e.key, key)) return e.value;47            }48            return null;49        }50 51        boolean remove(K key) {52            int i = indexFor(key);53            Entry<K, V> prev = null, e = buckets[i];54            while (e != null) {55                if (java.util.Objects.equals(e.key, key)) {56                    if (prev == null) buckets[i] = e.next; else prev.next = e.next;57                    size--; return true;58                }59                prev = e; e = e.next;60            }61            return false;62        }63 64        int size() { return size; }65 66        @SuppressWarnings("unchecked")67        private void resize() {68            Entry<K, V>[] old = buckets;69            buckets = new Entry[old.length * 2];70            size = 0;71            for (Entry<K, V> head : old)72                for (Entry<K, V> e = head; e != null; e = e.next) put(e.key, e.value);73        }74    }75 76    public static void main(String[] args) {77        MyHashMap<String, Integer> map = new MyHashMap<>();78        map.put("one", 1); map.put("two", 2); map.put("three", 3);79        map.put("two", 22);                            // update existing80        System.out.println("get(two)=" + map.get("two") + " get(missing)=" + map.get("x"));81        System.out.println("size=" + map.size());82        System.out.println("remove(one)=" + map.remove("one") + " size=" + map.size());83 84        // Force several inserts to trigger a resize85        for (int i = 0; i < 20; i++) map.put("k" + i, i);86        System.out.println("after many puts size=" + map.size() + " get(k15)=" + map.get("k15"));87    }88}