public class LockedBucketMap {
    Object[] locks;
    Node[] buckets;

    LockedBucketMap() {
        this(256);
    }

    LockedBucketMap(int numBuckets) {
        locks = new Object[numBuckets];
        buckets = new Node[numBuckets];

        for (int i = 0; i < locks.length; i++) {
            locks[i] = new Object();
        }
    }

    Object get(Object key) {
        int hash = getHash(key);
        Node node = null;
        Object value = null;

        synchronized (locks[hash]) {
            node = buckets[hash];

            while (node != null) {
                if (node.key.equals(key)) {
                    return node.value;
                }
                node = node.next;
            }
        }
        return value;
    }

    int getHash(Object key) {
        return key.hashCode() % buckets.length;
    }

    void put(Object key, Object value) {
        int hash = getHash(key);
        System.out.println("hash=" + hash);

        Node node = null;
        synchronized (locks[hash]) {
            try {
                node = buckets[hash];
                if (node == null) {
                    System.out.println("make first node: " + value);
                    buckets[hash] = new Node(key, value);
                } else {
                    while (node.next != null) {
                        node = node.next;
                    }
                    node.next = new Node(key, value);
                    System.out.println("next node: " + node.next);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    class Node {

        Object key;
        Object value;
        Node next;

        public Node(Object key, Object value) {
            this.key = key;
            this.value = value;
        }

        public String toString() {
            return value.toString();
        }
    }
}

