panda.lang.collection.CaseInsensitiveMap Maven / Gradle / Ivy
package panda.lang.collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Implementation of a Map
that ignores the case of the
* keys. if you do
*
*
* put("test", "1");
*
* put("TEST", "2");
*
*
* the second put
overwrites the value of the first one,
* because the keys are considered to be equal. With
*
*
* get("TesT");
*
*
* you'll get the result "2"
.
* If you iterate through the keys (using either keySet
or
* entrySet
), you'll get the first added version of the key,
* in the above case, you'll get "test"
.
* It is allowed to use non-strings as keys. In this case the Map
* behaves like a usual HashMap
.
* Note: This class is similar to a TreeMap(String.CASE_INSENSITIVE_ORDER)
* except that non-strings do not throw a ClassCastException
* and that keys are not sorted.
*
* @param the type of keys maintained by this map
* @param the type of mapped values
*
*/
public class CaseInsensitiveMap implements Map, Cloneable {
private transient Map keys;
private transient Map cmap;
public CaseInsensitiveMap() {
this.keys = new HashMap();
this.cmap = init();
}
public CaseInsensitiveMap(Map map) {
this();
putAll(map);
}
protected Map init() {
return new HashMap();
}
protected Object toCompareKey(Object key) {
return key instanceof String ? ((String)key).toLowerCase() : key;
}
@Override
public void clear() {
keys.clear();
cmap.clear();
}
@Override
public boolean containsKey(Object key) {
Object ck = toCompareKey(key);
if (keys.containsKey(ck)) {
K mk = keys.get(ck);
if (cmap.containsKey(mk)) {
return true;
}
keys.remove(ck);
}
return false;
}
@Override
public boolean containsValue(Object value) {
return cmap.containsValue(value);
}
@Override
public Set> entrySet() {
return cmap.entrySet();
}
@Override
public V get(Object key) {
Object ck = toCompareKey(key);
if (keys.containsKey(ck)) {
K mk = keys.get(ck);
return cmap.get(mk);
}
return null;
}
@Override
public boolean isEmpty() {
return cmap.isEmpty();
}
@Override
public Set keySet() {
return new Set() {
@Override
public int size() {
return cmap.keySet().size();
}
@Override
public boolean isEmpty() {
return cmap.keySet().isEmpty();
}
@Override
public boolean contains(Object o) {
return containsKey(o);
}
@Override
public Iterator iterator() {
return cmap.keySet().iterator();
}
@Override
public Object[] toArray() {
return cmap.keySet().toArray();
}
@Override
public T[] toArray(T[] a) {
return cmap.keySet().toArray(a);
}
@Override
public boolean add(K e) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
Object ck = toCompareKey(o);
if (keys.containsKey(ck)) {
K mk = keys.remove(ck);
cmap.remove(mk);
return true;
}
return false;
}
@Override
public boolean containsAll(Collection> c) {
for (Object e : c) {
if (!containsKey(e)) {
return false;
}
}
return true;
}
@Override
public boolean addAll(Collection extends K> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection> c) {
boolean modified = false;
Set