/*
* Copyright 2003-2010 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.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* This represents a
* @author <a href="mailto:blackdrag@gmx.org">Jochen "blackdrag" Theodorou</a>
*/
public class ListHashMap<K,V> implements Map<K,V> {
private int listFill = 0;
private Object[] listKeys;
private Object[] listValues;
private int size = 0;
private Map<K,V> innerMap;
private final int maxListFill;
public ListHashMap() {
this(3);
}
public ListHashMap(int listSize){
this.listKeys = new Object[listSize];
this.listValues = new Object[listSize];
maxListFill = listSize;
}
public void clear() {
listFill = 0;
innerMap = null;
for (int i=0; i<maxListFill; i++) {
listValues[i] = null;
listKeys[i] = null;
}
}
public boolean containsKey(Object key) {
if (size<maxListFill) {
for (int i=0; i<listFill; i++) {
if (listKeys[i].equals(key)) return true;
}
return false;
} else {
return innerMap.containsKey(key);
}
}
public boolean containsValue(Object value) {
if (size<maxListFill) {
for (int i=0; i<listFill; i++) {
if (listValues[i].equals(value)) return true;
}
return false;
} else {
return innerMap.containsValue(value);
}
}
private Map<K,V> makeMap() {
Map<K,V> m = new HashMap();
for (int i=0; i<size; i++) {
m.put((K) listKeys[i], (V) listValues[i]);
}
return m;
}
public Set<java.util.Map.Entry<K, V>> entrySet() {
Map m;
if (size>maxListFill) {
m = innerMap;
} else {
m = makeMap();
}
return m.entrySet();
}
public V get(Object key) {
if(size==0) return null;
if (size<maxListFill) {
for (int i=0; i<maxListFill; i++) {
if (listKeys[i].equals(key)) return (V) listValues[i];
}
return null;
} else {
return innerMap.get(key);
}
}
public boolean isEmpty() {
return size == 0;
}
public Set<K> keySet() {
Map m;
if (size>=maxListFill) {
m = innerMap;
} else {
m = makeMap();
}
return m.keySet();
}
public V put(K key, V value) {
if (size<maxListFill) {
for (int i=0; i<listFill; i++) {
if (listKeys[i].equals(key)) {
V old = (V) listValues[i];
listValues[i] = value;
return old;
}
}
if (size<maxListFill-1) {
size++;
listKeys[listFill] = key;
listValues[listFill] = value;
listFill++;
return null;
} else {
innerMap = makeMap();
}
}
return innerMap.put(key,value);
}
public void putAll(Map<? extends K, ? extends V> m) {
if (size+m.size()<maxListFill) {
for (Entry<? extends K,? extends V> entry : m.entrySet()) {
listKeys[listFill] = entry.getKey();
listValues[listFill] = entry.getValue();
listFill++;
}
size += m.size();
return;
}
if (size<maxListFill) innerMap = makeMap();
innerMap.putAll(m);
size += m.size();
}
public V remove(Object key) {
if (size<maxListFill) {
for (int i=0; i<listFill; i++) {
if (listKeys[i].equals(key)) {
V old = (V) listValues[i];
listFill--; size--;
listValues[i] = listValues[listFill];
listKeys[i] = listValues[listFill];
return old;
}
}
return null;
} else {
V old = innerMap.remove(key);
if (old!=null) size--;
if (size<maxListFill) {
mapToList();
}
return old;
}
}
private void mapToList() {
int i = 0;
for (Entry<? extends K,? extends V> entry : innerMap.entrySet()) {
listKeys[i] = entry.getKey();
listValues[i] = entry.getValue();
i++;
}
listFill = innerMap.size();
innerMap = null;
}
public int size() {
return size;
}
public Collection<V> values() {
if (size<maxListFill) {
ArrayList<V> list = new ArrayList(size);
for (int i=0; i<listFill; i++) {
list.add((V) listValues[i]);
}
return list;
} else {
return innerMap.values();
}
}
}