blob: 3226858894e0d2668c4b264213720f3ee89b4ecb [file] [log] [blame]
/*
* Copyright 2003-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.groovy.reflection;
import java.util.NoSuchElementException;
public class ComplexKeyHashMap
{
public static class Entry {
public int hash;
public Entry next;
public Object value;
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
protected Entry table [];
protected static final int DEFAULT_CAPACITY = 32;
protected static final int MINIMUM_CAPACITY = 4;
protected static final int MAXIMUM_CAPACITY = 1 << 28;
protected int size;
protected transient int threshold;
public ComplexKeyHashMap() {
init(DEFAULT_CAPACITY);
}
public ComplexKeyHashMap(boolean b) {
}
public ComplexKeyHashMap(int expectedMaxSize) {
init (capacity(expectedMaxSize));
}
public static int hash(int h) {
h += ~(h << 9);
h ^= (h >>> 14);
h += (h << 4);
h ^= (h >>> 10);
return h;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void clear() {
Object[] tab = table;
for (int i = 0; i < tab.length; i++)
tab[i] = null;
size = 0;
}
public void init(int initCapacity) {
threshold = (initCapacity * 6)/8;
table = new Entry[initCapacity];
}
public void resize(int newLength) {
Entry[] oldTable = table;
int oldLength = table.length;
Entry[] newTable = new Entry[newLength];
for (int j = 0; j < oldLength; j++) {
for (Entry e = oldTable [j]; e != null;) {
Entry next = e.next;
int index = e.hash & (newLength-1);
e.next = newTable[index];
newTable [index] = e;
e = next;
}
}
table = newTable;
threshold = (6 * newLength) / 8;
}
private int capacity(int expectedMaxSize) {
// Compute min capacity for expectedMaxSize given a load factor of 3/4
int minCapacity = (8 * expectedMaxSize)/6;
// Compute the appropriate capacity
int result;
if (minCapacity > MAXIMUM_CAPACITY || minCapacity < 0) {
result = MAXIMUM_CAPACITY;
} else {
result = MINIMUM_CAPACITY;
while (result < minCapacity)
result <<= 1;
}
return result;
}
public interface EntryIterator {
boolean hasNext ();
Entry next ();
}
public ComplexKeyHashMap.Entry[] getTable() {
return table;
}
public EntryIterator getEntrySetIterator() {
return new EntryIterator() {
Entry next; // next entry to return
int index; // current slot
Entry current; // current entry
{
Entry[] t = table;
int i = t.length;
Entry n = null;
if (size != 0) { // advance to first entry
while (i > 0 && (n = t[--i]) == null) {}
}
next = n;
index = i;
}
public boolean hasNext() {
return next != null;
}
public Entry next() {
return nextEntry();
}
Entry nextEntry() {
Entry e = next;
if (e == null)
throw new NoSuchElementException();
Entry n = e.next;
Entry[] t = table;
int i = index;
while (n == null && i > 0)
n = t[--i];
index = i;
next = n;
return current = e;
}
};
}
}