gnu.trove.set.hash.TLinkedHashSet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of trove4j Show documentation
Show all versions of trove4j Show documentation
The Trove library provides high speed regular and primitive
collections for Java.
package gnu.trove.set.hash;
import gnu.trove.iterator.TIntIterator;
import gnu.trove.iterator.hash.TObjectHashIterator;
import gnu.trove.list.TIntList;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.list.linked.TIntLinkedList;
import gnu.trove.procedure.TIntProcedure;
import gnu.trove.procedure.TObjectProcedure;
import java.io.IOException;
import java.io.ObjectOutput;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
/**
* Created by IntelliJ IDEA.
* User: Johan
* Date: 15/03/11
* Time: 18:15
* To change this template use File | Settings | File Templates.
*/
public class TLinkedHashSet extends THashSet {
TIntList order;
/**
* Creates a new THashSet
instance with the default
* capacity and load factor.
*/
public TLinkedHashSet() {
}
/**
* Creates a new THashSet
instance with a prime
* capacity equal to or greater than initialCapacity and
* with the default load factor.
*
* @param initialCapacity an int
value
*/
public TLinkedHashSet(int initialCapacity) {
super(initialCapacity);
}
/**
* Creates a new THashSet
instance with a prime
* capacity equal to or greater than initialCapacity and
* with the specified load factor.
*
* @param initialCapacity an int
value
* @param loadFactor a float
value
*/
public TLinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
/**
* Creates a new THashSet
instance containing the
* elements of collection.
*
* @param es a Collection
value
*/
public TLinkedHashSet(Collection extends E> es) {
super(es);
}
/**
* initializes the Object set of this hash table.
*
* @param initialCapacity an int
value
* @return an int
value
*/
@Override
public int setUp(int initialCapacity) {
order = new TIntArrayList(initialCapacity) {
/**
* Grow the internal array as needed to accommodate the specified number of elements.
* The size of the array bytes on each resize unless capacity requires more than twice
* the current capacity.
*/
@Override
public void ensureCapacity(int capacity) {
if (capacity > _data.length) {
int newCap = Math.max(_set.length, capacity);
int[] tmp = new int[newCap];
System.arraycopy(_data, 0, tmp, 0, _data.length);
_data = tmp;
}
}
};
return super.setUp(initialCapacity); //To change body of overridden methods use File | Settings | File Templates.
}
/**
* Empties the set.
*/
@Override
public void clear() {
super.clear();
order.clear();
}
@Override
public String toString() {
final StringBuilder buf = new StringBuilder("{");
boolean first = true;
for (Iterator it = iterator(); it.hasNext();) {
if (first) {
first = false;
} else {
buf.append(", ");
}
buf.append(it.next());
}
buf.append("}");
return buf.toString();
}
/**
* Inserts a value into the set.
*
* @param obj an Object
value
* @return true if the set was modified by the add operation
*/
@Override
public boolean add(E obj) {
int index = insertKey(obj);
if (index < 0) {
return false; // already present in set, nothing to add
}
if (!order.add(index))
throw new IllegalStateException("Order not changed after insert");
postInsertHook(consumeFreeSlot);
return true; // yes, we added something
}
@Override
protected void removeAt(int index) {
// Remove from order first since super.removeAt can trigger compaction
// making the index invalid afterwards
order.remove(index);
super.removeAt(index);
}
/**
* Expands the set to accommodate new values.
*
* @param newCapacity an int
value
*/
@Override
protected void rehash(int newCapacity) {
TIntLinkedList oldOrder = new TIntLinkedList(order);
int oldSize = size();
Object oldSet[] = _set;
order.clear();
_set = new Object[newCapacity];
Arrays.fill(_set, FREE);
for (TIntIterator iterator = oldOrder.iterator(); iterator.hasNext();) {
int i = iterator.next();
E o = (E) oldSet[i];
if (o == FREE || o == REMOVED) {
throw new IllegalStateException("Iterating over empty location while rehashing");
}
if (o != FREE && o != REMOVED) {
int index = insertKey(o);
if (index < 0) { // everyone pays for this because some people can't RTFM
throwObjectContractViolation(_set[(-index - 1)], o, size(), oldSize, oldSet);
}
if (!order.add(index))
throw new IllegalStateException("Order not changed after insert");
}
}
}
class WriteProcedure implements TIntProcedure {
final ObjectOutput output;
IOException ioException;
WriteProcedure(ObjectOutput output) {
this.output = output;
}
public IOException getIoException() {
return ioException;
}
public boolean execute(int value) {
try {
output.writeObject(_set[value]);
} catch (IOException e) {
ioException = e;
return false;
}
return true;
}
}
@Override
protected void writeEntries(ObjectOutput out) throws IOException {
// ENTRIES
WriteProcedure writeProcedure = new WriteProcedure(out);
if (!order.forEach(writeProcedure))
throw writeProcedure.getIoException();
}
/**
* Creates an iterator over the values of the set. The iterator
* supports element deletion.
*
* @return an Iterator
value
*/
@Override
public TObjectHashIterator iterator() {
return new TObjectHashIterator(this) {
TIntIterator localIterator = order.iterator();
int lastIndex;
/**
* Moves the iterator to the next Object and returns it.
*
* @return an Object
value
* @throws java.util.ConcurrentModificationException
* if the structure
* was changed using a method that isn't on this iterator.
* @throws java.util.NoSuchElementException
* if this is called on an
* exhausted iterator.
*/
@Override
public E next() {
lastIndex = localIterator.next();
return objectAtIndex(lastIndex);
}
/**
* Returns true if the iterator can be advanced past its current
* location.
*
* @return a boolean
value
*/
@Override
public boolean hasNext() {
return localIterator.hasNext(); //To change body of overridden methods use File | Settings | File Templates.
}
/**
* Removes the last entry returned by the iterator.
* Invoking this method more than once for a single entry
* will leave the underlying data structure in a confused
* state.
*/
@Override
public void remove() {
// Remove for iterator first
localIterator.remove();
// the removal within removeAt() will not change the collection
// but the localIterator will remain valid
try {
_hash.tempDisableAutoCompaction();
TLinkedHashSet.this.removeAt(lastIndex);
} finally {
_hash.reenableAutoCompaction(false);
}
}
}; //To change body of overridden methods use File | Settings | File Templates.
}
class ForEachProcedure implements TIntProcedure {
boolean changed = false;
final Object[] set;
final TObjectProcedure super E> procedure;
public ForEachProcedure(Object[] set, TObjectProcedure super E> procedure) {
this.set = set;
this.procedure = procedure;
}
/**
* Executes this procedure. A false return value indicates that
* the application executing this procedure should not invoke this
* procedure again.
*
* @param value a value of type int
* @return true if additional invocations of the procedure are
* allowed.
*/
public boolean execute(int value) {
return procedure.execute((E) set[value]);
}
}
/**
* Executes procedure for each element in the set.
*
* @param procedure a TObjectProcedure
value
* @return false if the loop over the set terminated because
* the procedure returned false for some value.
*/
@Override
public boolean forEach(TObjectProcedure super E> procedure) {
ForEachProcedure forEachProcedure = new ForEachProcedure(_set, procedure);
return order.forEach(forEachProcedure);
}
}