All Downloads are FREE. Search and download functionalities are using the official Maven repository.

webit.script.util.ClassMap Maven / Gradle / Ivy

// Copyright (c) 2013-2014, Webit Team. All Rights Reserved.
package webit.script.util;

public final class ClassMap {

    private static final int MAXIMUM_CAPACITY = 1 << 29;

    private Entry[] table;
    private int threshold;
    private int size;

    @SuppressWarnings("unchecked")
    public ClassMap(int initialCapacity) {
        int initlen;
        if (initialCapacity > MAXIMUM_CAPACITY) {
            initlen = MAXIMUM_CAPACITY;
        } else {
            initlen = 16;
            while (initlen < initialCapacity) {
                initlen <<= 1;
            }
        }
        this.table = new Entry[initlen];
        this.threshold = (int) (initlen * 0.75f);
    }

    public ClassMap() {
        this(64);
    }

    public int size() {
        return size;
    }

    public V unsafeGet(final Class key) {
        Entry e;
        final Entry[] tab;
        e = (tab = table)[key.hashCode() & (tab.length - 1)];
        while (e != null) {
            if (key == e.key) {
                return e.value;
            }
            e = e.next;
        }
        return null;
    }

    public V get(Class key) {
        synchronized (this) {
            return unsafeGet(key);
        }
    }

    @SuppressWarnings("unchecked")
    private void resize() {
        synchronized (this) {
            if (size < threshold) {
                return;
            }
            final Entry[] oldTable = table;
            final int oldCapacity = oldTable.length;

            final int newCapacity = oldCapacity << 1;
            if (newCapacity > MAXIMUM_CAPACITY) {
                if (threshold == MAXIMUM_CAPACITY - 1) {
                    throw new IllegalStateException("Capacity exhausted.");
                }
                threshold = MAXIMUM_CAPACITY - 1;
                return;
            }
            final int newMark = newCapacity - 1;
            final Entry[] newTable = new Entry[newCapacity];

            for (int i = oldCapacity; i-- > 0;) {
                int index;
                for (Entry old = oldTable[i], e; old != null;) {
                    e = old;
                    old = old.next;

                    index = e.id & newMark;
                    e.next = newTable[index];
                    newTable[index] = e;
                }
            }

            this.threshold = (int) (newCapacity * 0.75f);
            //Note: must at Last
            this.table = newTable;
        }
    }

    @SuppressWarnings("unchecked")
    public V putIfAbsent(Class key, V value) {
        synchronized (this) {
            final int id;
            int index;

            Entry[] tab;
            Entry e = (tab = table)[index = (id = key.hashCode()) & (tab.length - 1)];
            for (; e != null; e = e.next) {
                if (key == e.key) {
                    return e.value;
                }
            }

            if (size >= threshold) {
                resize();
                tab = table;
                index = id & (tab.length - 1);
            }

            // creates the new entry.
            tab[index] = new Entry(id, key, value, tab[index]);
            size++;
            return value;
        }
    }

    private static final class Entry {

        final int id;
        final Class key;
        final V value;
        Entry next;

        Entry(int id, Class key, V value, Entry next) {
            this.value = value;
            this.id = id;
            this.key = key;
            this.next = next;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy