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

IdentityHashtable

public class IdentityHashtable extends Dictionary implements Serializable, Cloneable
INTERNAL:

Purpose: Define a {@link Hashtable} 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.

Fields Summary
static final long
serialVersionUID
static final int
DEFAULT_INITIAL_CAPACITY
static final int
MAXIMUM_CAPACITY
static final float
DEFAULT_LOAD_FACTOR
static final int
KEYS
An "enum" of Enumeration types.
static final int
ELEMENTS
An "enum" of Enumeration types.
private static EmptyEnumerator
emptyEnumerator
protected transient Entry[]
entries
protected transient int
count
protected int
threshold
protected float
loadFactor
Constructors Summary
public IdentityHashtable(int initialCapacity, float loadFactor)
Constructs a new IdentityHashtable with the given initial capacity and the given loadFactor.

param
initialCapacity the initial capacity of this IdentityHashtable.
param
loadFactor the loadFactor of the IdentityHashtable.
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 IdentityHashtable(int initialCapacity)
Constructs a new IdentityHashtable with the given initial capacity and a default loadFactor of 0.75.

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

        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    
public IdentityHashtable()
Constructs a new IdentityHashtable 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];
    
Methods Summary
public synchronized voidclear()
Removes all of the mappings from this IdentityHashtable.

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

return
a shallow copy of this IdentityHashtable.

        try {
            Entry[] copyOfEntries = entries;
            IdentityHashtable clone = (IdentityHashtable)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;
            }
            return clone;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError();
        }
    
public synchronized booleancontains(java.lang.Object obj)
Returns true if this IdentityHashtable contains the given object. Equality is tested by the equals() method.

param
obj the object to find.
return
true if this IdentityHashtable 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 synchronized booleancontainsKey(java.lang.Object key)
Returns true if this IdentityHashtable contains a mapping for the given key. Equality is tested by reference.

param
key object to be used as a key into this IdentityHashtable.
return
true if this IdentityHashtable 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 synchronized java.util.Enumerationelements()

        if (count == 0) {
            return emptyEnumerator;
        } else {
            return new Enumerator(ELEMENTS);
        }
    
public synchronized java.lang.Objectget(java.lang.Object key)
Returns the value to which the given key is mapped in this IdentityHashtable. Returns null if this IdentityHashtable contains no mapping for this key.

return
the value to which this IdentityHashtable 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;
    
public booleanisEmpty()

return
true if this IdentityHashtable is empty.

        return (count == 0);
    
public synchronized java.util.Enumerationkeys()

        if (count == 0) {
            return emptyEnumerator;
        } else {
            return new Enumerator(KEYS);
        }
    
public synchronized java.lang.Objectput(java.lang.Object key, java.lang.Object obj)
Associate the given object with the given key in this IdentityHashtable, 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 IdentityHashtable 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;
            }
        }

        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;
    
private voidreadObject(java.io.ObjectInputStream s)
Deserialize the IdentityHashtable 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 IdentityHashtable exceeds its current threshold.

        int oldCapacity = entries.length;
        Entry[] oldEntries = entries;
        int newCapacity = (oldCapacity * 2) + 1;
        Entry[] newEntries = new Entry[newCapacity];
        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 synchronized java.lang.Objectremove(java.lang.Object key)
Removes the mapping (key and its corresponding value) from this IdentityHashtable, if present.

param
key key whose mapping is to be removed from the map.
return
the previous object for key or null if this IdentityHashtable 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 IdentityHashtable.

        return count;
    
public synchronized java.lang.StringtoString()
Return the string representation of this IdentityHashtable.

return
the string representation of this IdentityHashtable.

        int max = size() - 1;
        StringBuffer buf = new StringBuffer();
        Enumeration k = keys();
        Enumeration e = elements();
        buf.append("{");
        for (int i = 0; i <= max; i++) {
            String s1 = k.nextElement().toString();
            String s2 = e.nextElement().toString();
            buf.append(s1 + "=" + s2);
            if (i < max) {
                buf.append(", ");
            }
        }
        buf.append("}");
        return buf.toString();
    
private voidwriteObject(java.io.ObjectOutputStream s)
Serialize the state of this IdentityHashtable to a stream.

serialData
The capacity of the IdentityHashtable (the length of the bucket array) is emitted (int), followed by the size of the IdentityHashtable, 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;
            }
        }