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

jodd.util.collection.ClassMap Maven / Gradle / Ivy

There is a newer version: 5.1.0-20190624
Show newest version
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package jodd.util.collection;

import java.util.Arrays;

/**
 * Storage for holding classes keys and values.
 * It is NOT a Map instance. It is very fast
 * on un-synchronized lookups, faster then HashMap.
 * Uses identity for checking if Class keys are equal.
 * 

* The initial version of this class was provided by @zqq90, from * WebIt-script * project. Thank you! */ public final class ClassMap { private static final int MAXIMUM_CAPACITY = 1 << 29; private Entry[] table; private int threshold; private int size; /** * Creates new map with given initial capacity. */ @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); } /** * Returns total number of stored classes. */ public int size() { return size; } /** * Returns a value associated to a key in unsafe, but very fast way. */ public V unsafeGet(final Class key) { final Entry[] tab = table; Entry e = (tab)[key.hashCode() & (tab.length - 1)]; while (e != null) { if (key == e.key) { return e.value; } e = e.next; } return null; } /** * Returns a value associated to a key in thread-safe way. */ public synchronized V get(Class key) { return unsafeGet(key); } @SuppressWarnings("unchecked") private void resize() { 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); // must be last this.table = newTable; } /** * Associates the specified value with the specified Class in this map. * Returns the previous value associated with key, or null * if there was no mapping for key. */ @SuppressWarnings("unchecked") public synchronized V put(Class key, V value) { final int id; int index; Entry[] tab = table; id = key.hashCode(); index = (id) & (tab.length - 1); Entry e = (tab)[index]; while (e != null) { if (key == e.key) { // identity check // key found, replace V existing = e.value; e.value = value; return existing; } e = e.next; } 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 null; } /** * Clears the class map. */ public synchronized void clear() { size = 0; Arrays.fill(table, null); } /** * Maps entry. */ private static final class Entry { final int id; final Class key; V value; Entry next; private 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