// // Copyright (c)1998-2011 Pearson Education, Inc. or its affiliate(s). // All rights reserved. // package openadk.util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * A fast and very light-weight Map implementation for very small collections of items (less than 10)<p> * This implementation is much more lightweight than a HashMap in that it uses less objects. It is also * very fast for small lists because it uses a linked list lookup rather than a bucket-based approach. * This list is not synchronized. * @author Andrew Elmhorst * * @param <K> The Type of the key for this Map * @param <V> The Type of the value for this Map */ public class LinkedListMap<K,V> implements Map<K,V> { private Entry<K,V> first; private Entry<K,V> last; private final boolean fCaseInsensitive; public LinkedListMap(){ fCaseInsensitive = false; } /** * Allows a case-insensitive instance to be created. If this Map is created * with a String type as the key, all values will be created in a case-insensitive * manner. * @param isCaseInsensitive */ public LinkedListMap(Boolean isCaseInsensitive ){ fCaseInsensitive = isCaseInsensitive; } /* (non-Javadoc) * @see java.util.Map#size() */ public int size() { int a = 0; Entry next = first; while( next != null ){ a++; next = next.nextEntry; } return a; } /* (non-Javadoc) * @see java.util.Map#isEmpty() */ public boolean isEmpty() { return first == null; } /* (non-Javadoc) * @see java.util.Map#containsKey(java.lang.Object) */ public boolean containsKey(Object arg0) { return getEntry( arg0 ) != null; } /* (non-Javadoc) * @see java.util.Map#containsValue(java.lang.Object) */ public boolean containsValue(Object arg0) { Entry<K,V> next = first; while( next != null ){ if( next.fValue.equals( arg0 )){ return true; } next = next.nextEntry; } return false; } /* (non-Javadoc) * @see java.util.Map#get(java.lang.Object) */ public V get(Object arg0) { Entry<K,V> value = getEntry( arg0 ); if( value == null ){ return null; } return value.fValue; } private Entry<K,V> getEntry( Object key ){ Entry<K,V> next = first; while( next != null ){ if( next.fKey.equals( key )){ return next; } next = next.nextEntry; } return null; } /* (non-Javadoc) * @see java.util.Map#put(K, V) */ @SuppressWarnings("unchecked") public V put(K key, V putValue ) { K usedKey = key; if( fCaseInsensitive && usedKey != null && usedKey instanceof String ){ usedKey = (K)usedKey.toString().toLowerCase(); } Entry<K,V> savedValue = getEntry( usedKey ); if( savedValue == null ){ Entry<K,V> candidate = new Entry<K,V>( last, null ); candidate.fKey = usedKey; candidate.fValue = putValue ; if( first == null ){ first = candidate; } else { last.nextEntry = candidate; } last = candidate; } else { savedValue.fValue = putValue ; } return putValue ; } /* (non-Javadoc) * @see java.util.Map#remove(java.lang.Object) */ public V remove(Object arg0) { Entry<K,V> value = getEntry( arg0 ); if( value == null ){ return null; } // Remove the item from the linked list if( value.previousEntry != null ){ value.previousEntry.nextEntry = value.nextEntry; } if( value.nextEntry != null ){ value.nextEntry.previousEntry = value.previousEntry; } if( value == first ){ first = value.nextEntry; } if( value == last ){ last = value.previousEntry; } return value.fValue; } /* (non-Javadoc) * @see java.util.Map#putAll(java.util.Map) */ public void putAll(Map<? extends K, ? extends V> arg0) { for( Map.Entry<? extends K,? extends V> entry : arg0.entrySet() ){ this.put( entry.getKey(), entry.getValue() ); } } /* (non-Javadoc) * @see java.util.Map#clear() */ public void clear() { first = null; last = null; } /* (non-Javadoc) * @see java.util.Map#keySet() */ public Set<K> keySet() { HashSet<K> set = new HashSet<K>(); Entry<K,V> next = first; while( next != null ){ set.add( next.getKey() ); next = next.nextEntry; } return set; } /* (non-Javadoc) * @see java.util.Map#values() */ public Collection<V> values() { Collection<V> list = new ArrayList<V>(); Entry<K,V> next = first; while( next != null ){ list.add( next.getValue() ); next = next.nextEntry; } return list; } /* (non-Javadoc) * @see java.util.Map#entrySet() */ public Set<Map.Entry<K,V>> entrySet() { HashSet<Map.Entry<K,V>> set = new HashSet<Map.Entry<K,V>>(); // iterate the list Entry<K,V> next = first; while( next != null ){ set.add( next ); next = next.nextEntry; } return set; } /** * The Map.Entry implementation for the LinkedListMap * @author Andrew * * @param <K> * @param <V> */ private static class Entry<K,V> implements Map.Entry<K,V> { protected K fKey; protected V fValue; protected Entry<K,V> nextEntry; protected Entry<K,V> previousEntry; public Entry( Entry<K,V> previous, Entry<K,V> next ) { previousEntry = previous; nextEntry = next; } public K getKey() { return fKey; } public V getValue() { return fValue; } public V setValue(V arg0) { fValue = arg0; return fValue; } } }