Collections Data Structure Java

/*
 * ArrayMap.java Created Aug 12, 2009 by Andrew Butler, PSL
 */
//package prisms.util;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
 * An ArrayMap is a very inefficient map type that is more robust in dealing
 * with changes to its keys than other maps. HashMaps and TreeMaps may "lose"
 * the reference to a value if the key to that value changes in a way that
 * causes it to map or compare differently. ArrayMap has no such limitations,
 * but it pays for this feature in its speed with large data sets. Searching and
 * insertion are both O(n). Another bonus feature is that ArrayMap relies only
 * on the equals method--it requires no contract with the hashCode() and no
 * comparators.
 * 
 * @param 
 *            The key type for this map
 * @param 
 *            The value type for this map
 */
public class ArrayMap implements Map {
  private Object[] theKeys;
  private Object[] theValues;
  /**
   * Creates an ArrayMap
   */
  public ArrayMap() {
    theKeys = new Object[0];
    theValues = new Object[0];
  }
  /**
   * @see java.util.Map#size()
   */
  public int size() {
    return theKeys.length;
  }
  /**
   * @see java.util.Map#isEmpty()
   */
  public boolean isEmpty() {
    return theKeys.length == 0;
  }
  /**
   * @see java.util.Map#get(java.lang.Object)
   */
  public V get(Object key) {
    for (int i = 0; i < theKeys.length; i++)
      if (equal(key, theKeys[i]))
        return (V) theValues[i];
    return null;
  }
  private static boolean equal(Object o1, Object o2) {
    return o1 == null ? o2 == null : o1.equals(o2);
  }
  /**
   * @see java.util.Map#containsKey(java.lang.Object)
   */
  public boolean containsKey(Object key) {
    for (int i = 0; i < theKeys.length; i++)
      if (equal(key, theKeys[i]))
        return true;
    return false;
  }
  /**
   * @see java.util.Map#containsValue(java.lang.Object)
   */
  public boolean containsValue(Object value) {
    for (int i = 0; i < theValues.length; i++)
      if (equal(value, theValues[i]))
        return true;
    return false;
  }
  /**
   * @see java.util.Map#put(java.lang.Object, java.lang.Object)
   */
  public V put(K key, V value) {
    for (int i = 0; i < theKeys.length; i++) {
      if (equal(key, theKeys[i])) {
        V old = (V) theValues[i];
        theKeys[i] = key;
        theValues[i] = value;
        return old;
      }
    }
    Object[] newKeys = add(theKeys, key);
    Object[] newVals = add(theValues, value);
    theKeys = newKeys;
    theValues = newVals;
    return null;
  }
  /**
   * @param 
   *            The type of the array
   * @param anArray
   *            The array to extend
   * @param anElement
   *            The element to add into anArray
   * @return A new array of length anArray.length+1 whose
   *         contents are those of anArray followed by
   *         anElement
   */
  public static  T[] add(T[] anArray, T anElement) {
    int len = anArray == null ? 0 : Array.getLength(anArray);
    return add(anArray, anElement, len);
  }
  /**
   * Inserts an element into the array
   * 
   * @param 
   *            The type of the object array
   * @param anArray
   *            The array to insert into
   * @param anElement
   *            The element to insert
   * @param anIndex
   *            The index for the new element
   * @return The new array with all elements of anArray, but with
   *         anElement inserted at index anIndex
   */
  public static  T[] add(T[] anArray, T anElement, int anIndex) {
    T[] ret;
    if (anArray == null) {
      if (anIndex != 0)
        throw new ArrayIndexOutOfBoundsException("Cannot set "
            + anIndex + " element in a null array");
      ret = (T[]) Array.newInstance(anElement.getClass(), 1);
      ret[0] = anElement;
      return ret;
    } else
      ret = (T[]) Array.newInstance(
          anArray.getClass().getComponentType(), anArray.length + 1);
    System.arraycopy(anArray, 0, ret, 0, anIndex);
    put(ret, anElement, anIndex);
    System.arraycopy(anArray, anIndex, ret, anIndex + 1, anArray.length
        - anIndex);
    return ret;
  }
  private static void put(Object array, Object element, int index) {
    try {
      if (array instanceof Object[]) {
        try {
          ((Object[]) array)[index] = element;
        } catch (ArrayStoreException e) {
          throw new IllegalArgumentException(e.getMessage()
              + ": "
              + (element == null ? "null" : element.getClass()
                  .getName()) + " into "
              + array.getClass().getName());
        }
      } else {
        try {
          Array.set(array, index, element);
        } catch (IllegalArgumentException e) {
          throw new IllegalArgumentException(e.getMessage()
              + ": "
              + (element == null ? "null" : element.getClass()
                  .getName()) + " into "
              + array.getClass().getName(), e);
        }
      }
    } catch (ArrayIndexOutOfBoundsException e) {
      throw new ArrayIndexOutOfBoundsException(index + " into "
          + Array.getLength(array));
    }
  }
  /**
   * @see java.util.Map#putAll(java.util.Map)
   */
  public void putAll(Map t) {
    for (Map.Entry entry : t.entrySet())
      put(entry.getKey(), entry.getValue());
  }
  /**
   * @see java.util.Map#remove(java.lang.Object)
   */
  public V remove(Object key) {
    for (int i = 0; i < theKeys.length; i++) {
      if (equal(theKeys[i], key)) {
        V old = (V) theValues[i];
        Object[] newKeys = remove(theKeys, i);
        Object[] newVals = remove(theValues, i);
        theKeys = newKeys;
        theValues = newVals;
        return old;
      }
    }
    return null;
  }
  /**
   * Removes the specified object from the array
   * 
   * @param 
   *            The type of the array
   * @param anArray
   *            The array to remove an element from
   * @param anIndex
   *            The index of the element to remove
   * @return A new array with all the elements of anArray except
   *         the element at anIndex
   */
  public static  T[] remove(T[] anArray, int anIndex) {
    T[] ret;
    if (anArray == null)
      return null;
    else {
      ret = (T[]) Array.newInstance(
          anArray.getClass().getComponentType(), anArray.length - 1);
    }
    System.arraycopy(anArray, 0, ret, 0, anIndex);
    System.arraycopy(anArray, anIndex + 1, ret, anIndex, anArray.length
        - anIndex - 1);
    return ret;
  }
  /**
   * @see java.util.Map#clear()
   */
  public void clear() {
    theKeys = new Object[0];
    theValues = new Object[0];
  }
  /**
   * @see java.util.Map#keySet()
   */
  public Set keySet() {
    final Object[] iterKeys = theKeys;
    return new java.util.AbstractSet() {
      @Override
      public int size() {
        return iterKeys.length;
      }
      @Override
      public Iterator iterator() {
        return new Iterator() {
          private int index = 0;
          public boolean hasNext() {
            return index < iterKeys.length;
          }
          public K next() {
            K ret = (K) iterKeys[index];
            index++;
            return ret;
          }
          public void remove() {
            ArrayMap.this.remove(iterKeys[index - 1]);
          }
        };
      }
    };
  }
  /**
   * @see java.util.Map#values()
   */
  public Collection values() {
    final Object[] iterKeys = theKeys;
    final Object[] iterVals = theValues;
    return new java.util.AbstractSet() {
      @Override
      public int size() {
        return iterVals.length;
      }
      @Override
      public Iterator iterator() {
        return new Iterator() {
          private int index = 0;
          public boolean hasNext() {
            return index < iterVals.length;
          }
          public V next() {
            V ret = (V) iterVals[index];
            index++;
            return ret;
          }
          public void remove() {
            ArrayMap.this.remove(iterKeys[index - 1]);
          }
        };
      }
    };
  }
  /**
   * @see java.util.Map#entrySet()
   */
  public Set> entrySet() {
    final Object[] iterKeys = theKeys;
    final Object[] iterVals = theValues;
    return new java.util.AbstractSet>() {
      @Override
      public int size() {
        return iterVals.length;
      }
      @Override
      public Iterator> iterator() {
        return new Iterator>() {
          private int index = 0;
          public boolean hasNext() {
            return index < iterVals.length;
          }
          public Map.Entry next() {
            final K entryKey = (K) iterKeys[index];
            final V[] entryVal = (V[]) new Object[] { iterVals[index] };
            Map.Entry ret = new Map.Entry() {
              public K getKey() {
                return entryKey;
              }
              public V getValue() {
                return entryVal[0];
              }
              public V setValue(V value) {
                ArrayMap.this.put(entryKey, value);
                V ret2 = entryVal[0];
                entryVal[0] = value;
                return ret2;
              }
            };
            index++;
            return ret;
          }
          public void remove() {
            ArrayMap.this.remove(iterKeys[index - 1]);
          }
        };
      }
    };
  }
}