FileDocCategorySizeDatePackage
TopLinkIdentityHashMap.javaAPI DocGlassfish v2 API26664Tue May 22 16:54:34 BST 2007oracle.toplink.essentials.internal.helper

TopLinkIdentityHashMap

public class TopLinkIdentityHashMap extends AbstractMap implements Serializable, Cloneable, Map
INTERNAL:

Purpose: Define a {@link Map} that manages key equality by reference, not equals(). This is required to track objects throughout the lifecycle of a {@link oracle.toplink.essentials.sessions.UnitOfWork}, regardless if the domain object redefines its equals() method. Additionally, this implementation does not permit nulls.

author
Mike Norman (since TopLink 10.1.3)

Fields Summary
static final long
serialVersionUID
static final int
DEFAULT_INITIAL_CAPACITY
static final int
MAXIMUM_CAPACITY
static final float
DEFAULT_LOAD_FACTOR
protected transient Entry[]
entries
protected transient int
count
private transient int
modCount
protected int
threshold
protected float
loadFactor
private transient Set
keySet
private transient Set
entrySet
private transient Collection
values
private static final int
KEYS
private static final int
VALUES
private static final int
ENTRIES
private static EmptyHashIterator
emptyHashIterator
Constructors Summary
public TopLinkIdentityHashMap(int initialCapacity, float loadFactor)
Constructs a new TopLinkIdentityHashMap with the given initial capacity and the given loadFactor.

param
initialCapacity the initial capacity of this TopLinkIdentityHashMap.
param
loadFactor the loadFactor of the TopLinkIdentityHashMap.
throws
IllegalArgumentException if the initial capacity is less than zero, or if the loadFactor is nonpositive.


                                                      
         
        if (initialCapacity < 0) {
            throw new IllegalArgumentException("Illegal initialCapacity: " + initialCapacity);
        }
        if (initialCapacity > MAXIMUM_CAPACITY) {
            initialCapacity = MAXIMUM_CAPACITY;
        }
        if ((loadFactor <= 0) || Float.isNaN(loadFactor)) {
            throw new IllegalArgumentException("Illegal loadFactor: " + loadFactor);
        }

        // Find a power of 2 >= initialCapacity
        int capacity = 1;
        while (capacity < initialCapacity) {
            capacity <<= 1;
        }
        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor);
        entries = new Entry[capacity];
    
public TopLinkIdentityHashMap(int initialCapacity)
Constructs a new TopLinkIdentityHashMap with the given initial capacity and a default loadFactor of 0.75.

param
initialCapacity the initial capacity of the TopLinkIdentityHashMap.
throws
IllegalArgumentException if the initial capacity is less than zero.

        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    
public TopLinkIdentityHashMap()
Constructs a new TopLinkIdentityHashMap with a default initial capacity of 32 and a loadfactor of 0.75.

        loadFactor = DEFAULT_LOAD_FACTOR;
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        entries = new Entry[DEFAULT_INITIAL_CAPACITY];
    
public TopLinkIdentityHashMap(Map m)
Constructs a new TopLinkIdentityHashMap with the same mappings as the given map. The TopLinkIdentityHashMap is created with a capacity sufficient to hold the elements of the given map.

param
m the map whose mappings are to be placed in the TopLinkIdentityHashMap.

        this(Math.max((int)(m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
        putAll(m);
    
Methods Summary
public voidclear()
Removes all of the mappings from this TopLinkIdentityHashMap.

        if (count > 0) {
            modCount++;
            Entry[] copyOfEntries = entries;
            for (int i = copyOfEntries.length; --i >= 0;) {
                copyOfEntries[i] = null;
            }
            count = 0;
        }
    
public java.lang.Objectclone()
Returns a shallow copy of this TopLinkIdentityHashMap (the elements are not cloned).

return
a shallow copy of this TopLinkIdentityHashMap.

        try {
            Entry[] copyOfEntries = entries;
            TopLinkIdentityHashMap clone = (TopLinkIdentityHashMap)super.clone();
            clone.entries = new Entry[copyOfEntries.length];
            for (int i = copyOfEntries.length; i-- > 0;) {
                clone.entries[i] = (copyOfEntries[i] != null) ? (Entry)copyOfEntries[i].clone() : null;
            }
            clone.keySet = null;
            clone.entrySet = null;
            clone.values = null;
            clone.modCount = 0;
            return clone;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError();
        }
    
public booleancontainsKey(java.lang.Object key)
Returns true if this TopLinkIdentityHashMap contains a mapping for the given key. Equality is tested by reference.

param
key object to be used as a key into this TopLinkIdentityHashMap.
return
true if this TopLinkIdentityHashMap contains a mapping for key.

        Entry[] copyOfEntries = entries;
        int hash = System.identityHashCode(key);
        int index = (hash & 0x7FFFFFFF) % copyOfEntries.length;
        for (Entry e = copyOfEntries[index]; e != null; e = e.next) {
            if (e.key == key) {
                return true;
            }
        }
        return false;
    
public booleancontainsValue(java.lang.Object obj)
Returns true if this TopLinkIdentityHashMap contains the given object. Equality is tested by the equals() method.

param
obj the object to find.
return
true if this TopLinkIdentityHashMap contains obj.
throws
NullPointerException if obj is null.

        if (obj == null) {
            throw new NullPointerException();
        }

        Entry[] copyOfEntries = entries;
        for (int i = copyOfEntries.length; i-- > 0;) {
            for (Entry e = copyOfEntries[i]; e != null; e = e.next) {
                if (e.value.equals(obj)) {
                    return true;
                }
            }
        }
        return false;
    
public java.util.SetentrySet()
Returns a collection view of the mappings contained in this TopLinkIdentityHashMap. Each element in the returned collection is a Map.Entry. The collection is backed by the map, so changes to the map are reflected in the collection, and vice versa. The collection supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Collection.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

return
a collection view of the mappings contained in this TopLinkIdentityHashMap.

        if (entrySet == null) {
            entrySet = new AbstractSet() {
                        public Iterator iterator() {
                            return getHashIterator(ENTRIES);
                        }

                        public boolean contains(Object o) {
                            if (!(o instanceof Map.Entry)) {
                                return false;
                            }

                            Map.Entry entry = (Map.Entry)o;
                            Object key = entry.getKey();
                            Entry[] copyOfEntries = entries;
                            int hash = System.identityHashCode(key);
                            int index = (hash & 0x7FFFFFFF) % copyOfEntries.length;
                            for (Entry e = copyOfEntries[index]; e != null; e = e.next) {
                                if ((e.hash == hash) && e.equals(entry)) {
                                    return true;
                                }
                            }
                            return false;
                        }

                        public boolean remove(Object o) {
                            if (!(o instanceof Map.Entry)) {
                                return false;
                            }

                            Map.Entry entry = (Map.Entry)o;
                            Object key = entry.getKey();
                            Entry[] copyOfEntries = entries;
                            int hash = System.identityHashCode(key);
                            int index = (hash & 0x7FFFFFFF) % copyOfEntries.length;
                            for (Entry e = copyOfEntries[index], prev = null; e != null;
                                     prev = e, e = e.next) {
                                if ((e.hash == hash) && e.equals(entry)) {
                                    modCount++;
                                    if (prev != null) {
                                        prev.next = e.next;
                                    } else {
                                        copyOfEntries[index] = e.next;
                                    }
                                    count--;
                                    e.value = null;
                                    return true;
                                }
                            }
                            return false;
                        }

                        public int size() {
                            return count;
                        }

                        public void clear() {
                            TopLinkIdentityHashMap.this.clear();
                        }
                    };
        }
        return entrySet;
    
public java.lang.Objectget(java.lang.Object key)
Returns the value to which the given key is mapped in this TopLinkIdentityHashMap. Returns null if this TopLinkIdentityHashMap contains no mapping for this key.

return
the value to which this TopLinkIdentityHashMap maps the given key.
param
key key whose associated value is to be returned.

        Entry[] copyOfEntries = entries;
        int hash = System.identityHashCode(key);
        int index = (hash & 0x7FFFFFFF) % copyOfEntries.length;
        for (Entry e = copyOfEntries[index]; e != null; e = e.next) {
            if (e.key == key) {
                return e.value;
            }
        }
        return null;
    
private java.util.IteratorgetHashIterator(int type)

        if (count == 0) {
            return emptyHashIterator;
        } else {
            return new HashIterator(type);
        }
    
public booleanisEmpty()

return
true if this TopLinkIdentityHashMap is empty.

        return (count == 0);
    
public java.util.SetkeySet()
Returns a set view of the keys contained in this TopLinkIdentityHashMap. The set is backed by the map, so changes to the map are reflected in the set, and vice versa. The set supports element removal, which removes the corresponding mapping from this map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

return
a set view of the keys contained in this TopLinkIdentityHashMap.


                                                                                    
       
        if (keySet == null) {
            keySet = new AbstractSet() {
                        public Iterator iterator() {
                            return getHashIterator(KEYS);
                        }

                        public int size() {
                            return count;
                        }

                        public boolean contains(Object o) {
                            return containsKey(o);
                        }

                        public boolean remove(Object o) {
                            int oldSize = count;
                            TopLinkIdentityHashMap.this.remove(o);
                            return count != oldSize;
                        }

                        public void clear() {
                            TopLinkIdentityHashMap.this.clear();
                        }
                    };
        }
        return keySet;
    
public java.lang.Objectput(java.lang.Object key, java.lang.Object obj)
Associate the given object with the given key in this TopLinkIdentityHashMap, replacing any existing mapping.

param
key key to map to given object.
param
obj object to be associated with key.
return
the previous object for key or null if this TopLinkIdentityHashMap did not have one.
throws
NullPointerException if obj is null.

        if (obj == null) {
            throw new NullPointerException();
        }

        Entry[] copyOfEntries = entries;
        int hash = System.identityHashCode(key);
        int index = (hash & 0x7FFFFFFF) % copyOfEntries.length;
        for (Entry e = copyOfEntries[index]; e != null; e = e.next) {
            if (e.key == key) {
                Object old = e.value;
                e.value = obj;
                return old;
            }
        }

        modCount++;
        if (count >= threshold) {
            rehash();
            copyOfEntries = entries;
            index = (hash & 0x7FFFFFFF) % copyOfEntries.length;
        }
        Entry e = new Entry(hash, key, obj, copyOfEntries[index]);
        copyOfEntries[index] = e;
        count++;
        return null;
    
public voidputAll(java.util.Map m)
Copies all of the mappings from the given map to this TopLinkIdentityHashMap, replacing any existing mappings.

param
m mappings to be stored in this TopLinkIdentityHashMap.
throws
NullPointerException if m is null.

        if (m == null) {
            throw new NullPointerException();
        }

        Iterator i = m.entrySet().iterator();
        while (i.hasNext()) {
            Map.Entry me = (Map.Entry)i.next();
            put(me.getKey(), me.getValue());
        }
    
private voidreadObject(java.io.ObjectInputStream s)
Deserialize the TopLinkIdentityHashMap from a stream.

        // Read in the threshold, loadfactor (and any hidden 'magic' stuff).
        s.defaultReadObject();

        // Read in number of buckets and allocate the bucket array;
        int numBuckets = s.readInt();
        entries = new Entry[numBuckets];
        // Read in size (count)
        int size = s.readInt();

        // Read the mappings and add to the TopLinkIdentityHashMap
        for (int i = 0; i < size; i++) {
            Object key = s.readObject();
            Object value = s.readObject();
            put(key, value);
        }
    
private voidrehash()
INTERNAL: Re-builds the internal array of Entry's with a larger capacity. This method is called automatically when the number of objects in this TopLinkIdentityHashMap exceeds its current threshold.

        int oldCapacity = entries.length;
        Entry[] oldEntries = entries;
        int newCapacity = (oldCapacity * 2) + 1;
        Entry[] newEntries = new Entry[newCapacity];
        modCount++;
        threshold = (int)(newCapacity * loadFactor);
        entries = newEntries;
        for (int i = oldCapacity; i-- > 0;) {
            for (Entry old = oldEntries[i]; old != null;) {
                Entry e = old;
                old = old.next;
                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                e.next = newEntries[index];
                newEntries[index] = e;
            }
        }
    
public java.lang.Objectremove(java.lang.Object key)
Removes the mapping (key and its corresponding value) from this TopLinkIdentityHashMap, if present.

param
key key whose mapping is to be removed from the map.
return
the previous object for key or null if this TopLinkIdentityHashMap did not have one.

        Entry[] copyOfEntries = entries;
        int hash = System.identityHashCode(key);
        int index = (hash & 0x7FFFFFFF) % copyOfEntries.length;
        for (Entry e = copyOfEntries[index], prev = null; e != null; prev = e, e = e.next) {
            if (e.key == key) {
                if (prev != null) {
                    prev.next = e.next;
                } else {
                    copyOfEntries[index] = e.next;
                }
                count--;
                return e.value;
            }
        }
        return null;
    
public intsize()

return
the size of this TopLinkIdentityHashMap.

        return count;
    
public java.util.Collectionvalues()
Returns a collection view of the values contained in this TopLinkIdentityHashMap. The collection is backed by the map, so changes to the map are reflected in the collection, and vice versa. The collection supports element removal, which removes the corresponding mapping from this map, via the Iterator.remove, Collection.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

return
a collection view of the values contained in this TopLinkIdentityHashMap.

        if (values == null) {
            values = new AbstractCollection() {
                        public Iterator iterator() {
                            return getHashIterator(VALUES);
                        }

                        public int size() {
                            return count;
                        }

                        public boolean contains(Object o) {
                            return containsValue(o);
                        }

                        public void clear() {
                            TopLinkIdentityHashMap.this.clear();
                        }
                    };
        }
        return values;
    
private voidwriteObject(java.io.ObjectOutputStream s)
Serialize the state of this TopLinkIdentityHashMap to a stream.

serialData
The capacity of the TopLinkIdentityHashMap (the length of the bucket array) is emitted (int), followed by the size of the TopLinkIdentityHashMap, followed by the key-value mappings (in no particular order).

        // Write out the threshold, loadfactor (and any hidden 'magic' stuff).
        s.defaultWriteObject();

        // Write out number of buckets
        s.writeInt(entries.length);
        // Write out count
        s.writeInt(count);
        // Write out contents
        for (int i = entries.length - 1; i >= 0; i--) {
            Entry entry = entries[i];
            while (entry != null) {
                s.writeObject(entry.key);
                s.writeObject(entry.value);
                entry = entry.next;
            }
        }