An ArrayMap is a very inefficient map type that is more robust in dealing with changes to its keys than other maps. : Map « Collections Data Structure « Java






An ArrayMap is a very inefficient map type that is more robust in dealing with changes to its keys than other maps.

      
/*
 * 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 <K>
 *            The key type for this map
 * @param <V>
 *            The value type for this map
 */
public class ArrayMap<K, V> implements Map<K, V> {
  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 <T>
   *            The type of the array
   * @param anArray
   *            The array to extend
   * @param anElement
   *            The element to add into <code>anArray</code>
   * @return A new array of length <code>anArray.length+1</code> whose
   *         contents are those of <code>anArray</code> followed by
   *         <code>anElement</code>
   */
  public static <T> 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 <T>
   *            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 <code>anArray</code>, but with
   *         <code>anElement</code> inserted at index <code>anIndex</code>
   */
  public static <T> 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<? extends K, ? extends V> t) {
    for (Map.Entry<? extends K, ? extends V> 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 <T>
   *            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 <code>anArray</code> except
   *         the element at <code>anIndex</code>
   */
  public static <T> 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<K> keySet() {
    final Object[] iterKeys = theKeys;
    return new java.util.AbstractSet<K>() {
      @Override
      public int size() {
        return iterKeys.length;
      }

      @Override
      public Iterator<K> iterator() {
        return new Iterator<K>() {
          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<V> values() {
    final Object[] iterKeys = theKeys;
    final Object[] iterVals = theValues;
    return new java.util.AbstractSet<V>() {
      @Override
      public int size() {
        return iterVals.length;
      }

      @Override
      public Iterator<V> iterator() {
        return new Iterator<V>() {
          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<Map.Entry<K, V>> entrySet() {
    final Object[] iterKeys = theKeys;
    final Object[] iterVals = theValues;
    return new java.util.AbstractSet<Map.Entry<K, V>>() {
      @Override
      public int size() {
        return iterVals.length;
      }

      @Override
      public Iterator<Map.Entry<K, V>> iterator() {
        return new Iterator<Map.Entry<K, V>>() {
          private int index = 0;

          public boolean hasNext() {
            return index < iterVals.length;
          }

          public Map.Entry<K, V> next() {
            final K entryKey = (K) iterKeys[index];
            final V[] entryVal = (V[]) new Object[] { iterVals[index] };
            Map.Entry<K, V> ret = new Map.Entry<K, V>() {
              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]);
          }
        };
      }
    };
  }
}

   
    
    
    
    
    
  








Related examples in the same category

1.Creating and storing arrays in a map
2.Sort based on the values
3.Get a key from value with an HashMap
4.Retrieve environment variables (JDK1.5)
5.Creating a Type-Specific Map: creates a map whose keys are Integer objects and values are String objects.
6.A map declared to hold objects of a type T can also hold objects that extend from T
7.A value retrieved from a type-specific collection does not need to be casted
8.Map techniques.
9.Create an array containing the keys in a map
10.Create an array containing the values in a map
11.Creating a Hash Table
12.Creating a Map That Retains Order-of-Insertion
13.Automatically Removing an Unreferenced Element from a Hash Table
14.Creating a Type-Specific Map [5.0]
15.Use Iterator to loop through the HashMap class
16.Create type specific collections
17.Convert Properties into Map
18.A java.util.Map implementation using reference values
19.Utility method that return a String representation of a map. The elements will be represented as "key = value"
20.Utility method that return a String representation of a map. The elements will be represented as "key = value" (tab)
21.This program demonstrates the use of a map with key type String and value type Employee
22.Format a Map
23.A Map implementation that dumps its content when memory runs low.
24.A Map that stores the values in files within a directory.
25.Map List
26.Multi Value Map Array List
27.Multi Value Map Linked HashSet
28.An object that maps keys to values, and values back to keys.
29.LRU Map
30.A map acts like array.
31.Order Retaining Map
32.BinaryMap class implements a map from objects to integer objects where the only value is the integer with value 1.
33.A space-optimized map for associating char keys with values.
34.A Map implementation that grows to a fixed size and then retains only a fixed number of the highest (largest) keys.
35.Class which creates mapping between keys and a list of values.
36.A map of values by class.
37.History Map
38.Sorts map by values in ascending order.
39.Map from a given key to a list of values
40.Map from a given key to a set of values
41.Class which keeps a set of values and assigns each value a unique positive index.
42.Array Map
43.Array map
44.This Map stores it's keys as strings in upper case, null and duplicate keys are not allowed
45.Map to string
46.A simple class that stores key Strings as char[]'s in a hash table.