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

TopLinkIdentityHashSet

public class TopLinkIdentityHashSet extends AbstractCollection implements Serializable, Set, Cloneable
INTERNAL:

Purpose: Define a {@link Set} that tests 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 allow null elements.

This class does not inherit from {@link AbstractSet} because the method {@link AbstractSet#removeAll removeAll(Collection c)} does not work correctly with reference equality testing (NB the Javadocs for {@link AbstractCollection} indicates that removeAll is an optional method).

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
protected int
threshold
protected float
loadFactor
Constructors Summary
public TopLinkIdentityHashSet(int initialCapacity, float loadFactor)
Constructs a new TopLinkIdentityHashSet with the given initial capacity and the given loadFactor.

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

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

        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    
public TopLinkIdentityHashSet()
Constructs a new TopLinkIdentityHashSet 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 TopLinkIdentityHashSet(Collection c)
Constructs a new TopLinkIdentityHashSet with the same contents as the given Collection. The new TopLinkIdentityHashSet is created with an initial capacity sufficient to hold the elements of the given Collection.

param
c the Collection whose contents are to be placed in the new TopLinkIdentityHashSet.

        this(Math.max((int)(c.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
        addAll(c);
    
Methods Summary
public booleanadd(java.lang.Object obj)
Adds the given object to this TopLinkIdentityHashSet.

param
obj object to add.
return
true if this TopLinkIdentityHashSet did not already contain obj.
throws
NullPointerException if obj is null.

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

        // Makes sure the object is not already in the TopLinkIdentityHashSet.
        Entry[] copyOfEntries = entries;
        int hash = System.identityHashCode(obj);
        int index = (hash & 0x7FFFFFFF) % copyOfEntries.length;
        for (Entry e = copyOfEntries[index]; e != null; e = e.next) {
            if ((e.hash == hash) && (obj == e.value)) {
                return false;
            }
        }

        if (count >= threshold) {
            // Rehash the table if the threshold is exceeded
            rehash();
            copyOfEntries = entries;
            index = (hash & 0x7FFFFFFF) % copyOfEntries.length;
        }

        // Creates the new entry.
        Entry e = new Entry(hash, obj, copyOfEntries[index]);
        copyOfEntries[index] = e;
        count++;
        return true;
    
public voidclear()
Removes all of the objects from this TopLinkIdentityHashSet.

        if (count > 0) {
            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 TopLinkIdentityHashSet (the elements are not cloned).

return
a shallow copy of this TopLinkIdentityHashSet.

        try {
            Entry[] copyOfEntries = entries;
            TopLinkIdentityHashSet clone = (TopLinkIdentityHashSet)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 booleancontains(java.lang.Object obj)
Returns true if this TopLinkIdentityHashSet contains the given object.

param
obj the object to find.
return
true if this TopLinkIdentityHashSet contains obj by reference.

        if (obj == null) {
            return false;
        }

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

return
true if this TopLinkIdentityHashSet is empty.

        return (count == 0);
    
public java.util.Iteratoriterator()
Get an iterator for this TopLinkIdentityHashSet

        return new TopLinkIdentityHashSetIterator();
    
private voidreadObject(java.io.ObjectInputStream s)
Deserialize the TopLinkIdentityHashSet 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 objects and add to the TopLinkIdentityHashSet
        for (int i = 0; i < size; i++) {
            add(s.readObject());
        }
    
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 TopLinkIdentityHashSet 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 booleanremove(java.lang.Object obj)
Removes the given object from this TopLinkIdentityHashSet, if present.

param
obj the object to be removed from this TopLinkIdentityHashSet.
return
true if this TopLinkIdentityHashSet contained obj.

        if (obj == null) {
            return false;
        }

        Entry[] copyOfEntries = entries;
        int hash = System.identityHashCode(obj);
        int index = (hash & 0x7FFFFFFF) % copyOfEntries.length;
        for (Entry e = copyOfEntries[index], prev = null; e != null; prev = e, e = e.next) {
            if ((e.hash == hash) && (obj == e.value)) {
                if (prev != null) {
                    prev.next = e.next;
                } else {
                    copyOfEntries[index] = e.next;
                }
                count--;
                return true;
            }
        }
        return false;
    
public booleanremoveAll(java.util.Collection c)
This implementation throws an UnsupportedOperationException because removeAll does not work correctly with reference equality testing.

        throw new UnsupportedOperationException("TopLinkIdentityHashSet removeAll");
    
public booleanretainAll(java.util.Collection c)
This implementation throws an UnsupportedOperationException. The Javadocs for {@link AbstractCollection} indicates that retainAll is an optional method.

        throw new UnsupportedOperationException("TopLinkIdentityHashSet retainAll");
    
public intsize()

return
the size of this TopLinkIdentityHashSet.

        return count;
    
private voidwriteObject(java.io.ObjectOutputStream s)
Serialize the state of this TopLinkIdentityHashSet to a stream.

serialData
The capacity of the TopLinkIdentityHashSet (the length of the bucket array) is emitted (int), followed by the size of the TopLinkIdentityHashSet, followed by the contents (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 (Iterator i = iterator(); i.hasNext();) {
            s.writeObject(i.next());
        }