Collections Data Structure Java

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat Middleware LLC.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 *
 */
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
 * A Map where keys are compared by object identity,
 * rather than equals().
 */
public final class IdentityMap implements Map {
  private final Map map;
  private transient Map.Entry[] entryArray = new Map.Entry[0];
  private transient boolean dirty = false;
  /**
   * Return a new instance of this class, with an undefined
   * iteration order.
   *
   * @param size The size of the map
   * @return Map
   */
  public static Map instantiate(int size) {
    return new IdentityMap( new HashMap( size ) );
  }
  /**
   * Return a new instance of this class, with iteration
   * order defined as the order in which entries were added
   *
   * @param size The size of the map to create
   * @return
   */
  public static Map instantiateSequenced(int size) {
    return new IdentityMap( new LinkedHashMap( size ) );
  }
  /**
   * Private ctor used in serialization.
   *
   * @param underlyingMap The delegate map.
   */
  private IdentityMap(Map underlyingMap) {
    map = underlyingMap;
    dirty = true;
  }
  /**
   * Return the map entries (as instances of Map.Entry in a collection that
   * is safe from concurrent modification). ie. we may safely add new instances to
   * the underlying Map during iteration of the entries().
   *
   * @param map
   * @return Collection
   */
  public static Map.Entry[] concurrentEntries(Map map) {
    return ( (IdentityMap) map ).entryArray();
  }
  public static List entries(Map map) {
    return ( (IdentityMap) map ).entryList();
  }
  public static Iterator keyIterator(Map map) {
    return ( (IdentityMap) map ).keyIterator();
  }
  public Iterator keyIterator() {
    return new KeyIterator( map.keySet().iterator() );
  }
  public static final class IdentityMapEntry implements java.util.Map.Entry {
    IdentityMapEntry(Object key, Object value) {
      this.key=key;
      this.value=value;
    }
    private Object key;
    private Object value;
    public Object getKey() {
      return key;
    }
    public Object getValue() {
      return value;
    }
    public Object setValue(Object value) {
      Object result = this.value;
      this.value = value;
      return result;
    }
  }
  public static final class IdentityKey implements Serializable {
    private Object key;
    IdentityKey(Object key) {
      this.key=key;
    }
    public boolean equals(Object other) {
      return key == ( (IdentityKey) other ).key;
    }
    public int hashCode() {
      return System.identityHashCode(key);
    }
    public String toString() {
      return key.toString();
    }
    public Object getRealKey() {
      return key;
    }
  }
  public int size() {
    return map.size();
  }
  public boolean isEmpty() {
    return map.isEmpty();
  }
  public boolean containsKey(Object key) {
    IdentityKey k = new IdentityKey(key);
    return map.containsKey(k);
  }
  public boolean containsValue(Object val) {
    return map.containsValue(val);
  }
  public Object get(Object key) {
    IdentityKey k = new IdentityKey(key);
    return map.get(k);
  }
  public Object put(Object key, Object value) {
    dirty = true;
    return map.put( new IdentityKey(key), value );
  }
  public Object remove(Object key) {
    dirty = true;
    IdentityKey k = new IdentityKey(key);
    return map.remove(k);
  }
  public void putAll(Map otherMap) {
    Iterator iter = otherMap.entrySet().iterator();
    while ( iter.hasNext() ) {
      Map.Entry me = (Map.Entry) iter.next();
      put( me.getKey(), me.getValue() );
    }
  }
  public void clear() {
    dirty = true;
    entryArray = null;
    map.clear();
  }
  public Set keySet() {
    // would need an IdentitySet for this!
    throw new UnsupportedOperationException();
  }
  public Collection values() {
    return map.values();
  }
  public Set entrySet() {
    Set set = new HashSet( map.size() );
    Iterator iter = map.entrySet().iterator();
    while ( iter.hasNext() ) {
      Map.Entry me = (Map.Entry) iter.next();
      set.add( new IdentityMapEntry( ( (IdentityKey) me.getKey() ).key, me.getValue() ) );
    }
    return set;
  }
  public List entryList() {
    ArrayList list = new ArrayList( map.size() );
    Iterator iter = map.entrySet().iterator();
    while ( iter.hasNext() ) {
      Map.Entry me = (Map.Entry) iter.next();
      list.add( new IdentityMapEntry( ( (IdentityKey) me.getKey() ).key, me.getValue() ) );
    }
    return list;
  }
  public Map.Entry[] entryArray() {
    if (dirty) {
      entryArray = new Map.Entry[ map.size() ];
      Iterator iter = map.entrySet().iterator();
      int i=0;
      while ( iter.hasNext() ) {
        Map.Entry me = (Map.Entry) iter.next();
        entryArray[i++] = new IdentityMapEntry( ( (IdentityKey) me.getKey() ).key, me.getValue() );
      }
      dirty = false;
    }
    return entryArray;
  }
  /**
   * Workaround for a JDK 1.4.1 bug where IdentityHashMaps are not
   * correctly deserialized.
   *
   * @param map
   * @return Object
   */
  public static Object serialize(Map map) {
    return ( (IdentityMap) map ).map;
  }
  /**
   * Workaround for a JDK 1.4.1 bug where IdentityHashMaps are not
   * correctly deserialized.
   *
   * @param o
   * @return Map
   */
  public static Map deserialize(Object o) {
    return new IdentityMap( (Map) o );
  }
  
  public String toString() {
    return map.toString();
  }
  public static Map invert(Map map) {
    Map result = instantiate( map.size() );
    Iterator iter = map.entrySet().iterator();
    while ( iter.hasNext() ) {
      Map.Entry me = (Map.Entry) iter.next();
      result.put( me.getValue(), me.getKey() );
    }
    return result;
  }
  static final class KeyIterator implements Iterator {
    private KeyIterator(Iterator iter) {
      identityKeyIterator = iter;
    }
    private final Iterator identityKeyIterator;
    public boolean hasNext() {
      return identityKeyIterator.hasNext();
    }
    public Object next() {
      return ( (IdentityKey) identityKeyIterator.next() ).key;
    }
    public void remove() {
      throw new UnsupportedOperationException();
    }
  }
}