/*
* Javolution - Java(TM) Solution for Real-Time and Embedded Systems
* Copyright (C) 2006 - Javolution (http://javolution.org/)
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software is
* freely granted, provided that this notice is preserved.
*/
package javolution.util;
import java.io.IOException;
import j2me.io.ObjectInputStream;
import j2me.io.ObjectOutputStream;
import j2me.util.Collection;
import j2me.util.Iterator;
import j2me.util.Set;
import javolution.context.ObjectFactory;
import javolution.lang.Reusable;
/**
* <p> This class represents a set collection backed by a {@link FastMap};
* smooth capacity increase and no rehashing ever performed.</p>
*
* <p> {@link FastSet}, as for any {@link FastCollection} sub-class, supports
* thread-safe fast iterations without using iterators. For example:[code]
* for (FastSet.Record r = set.head(), end = set.tail(); (r = r.getNext()) != end;) {
* Object value = set.valueOf(r);
* }[/code]</p>
*
* @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
* @version 4.2, December 18, 2006
*/
public class FastSet/*<E>*/ extends FastCollection/*<E>*/ implements Set/*<E>*/, Reusable {
/**
* Holds the set factory.
*/
private static final ObjectFactory FACTORY = new ObjectFactory() {
public Object create() {
return new FastSet();
}
};
/**
* Holds the backing map.
*/
private transient FastMap _map;
/**
* Creates a set of small initial capacity.
*/
public FastSet() {
this(new FastMap());
}
/**
* Creates a persistent set associated to the specified unique identifier
* (convenience method).
*
* @param id the unique identifier for this map.
* @throws IllegalArgumentException if the identifier is not unique.
* @see javolution.context.PersistentContext.Reference
*/
public FastSet(String id) {
this(new FastMap(id));
}
/**
* Creates a set of specified initial capacity; unless the set size
* reaches the specified capacity, operations on this set will not allocate
* memory (no lazy object creation).
*
* @param capacity the initial capacity.
*/
public FastSet(int capacity) {
this(new FastMap(capacity));
}
/**
* Creates a set containing the specified elements, in the order they
* are returned by the set iterator.
*
* @param elements the elements to be placed into this fast set.
*/
public FastSet(Set/*<? extends E>*/ elements) {
this(new FastMap(elements.size()));
addAll(elements);
}
/**
* Creates a set implemented using the specified map.
*
* @param map the backing map.
*/
private FastSet(FastMap map) {
_map = map;
}
/**
* Returns a new, preallocated or {@link #recycle recycled} set instance
* (on the stack when executing in a {@link javolution.context.StackContext
* StackContext}).
*
* @return a new, preallocated or recycled set instance.
*/
public static /*<E>*/ FastSet/*<E>*/ newInstance() {
return (FastSet/*<E>*/) FACTORY.object();
}
/**
* Recycles a set {@link #newInstance() instance} immediately
* (on the stack when executing in a {@link javolution.context.StackContext
* StackContext}).
*/
public static void recycle(FastSet instance) {
FACTORY.recycle(instance);
}
/**
* Returns the number of elements in this set (its cardinality).
*
* @return the number of elements in this set (its cardinality).
*/
public final int size() {
return _map.size();
}
/**
* Adds the specified value to this set if it is not already present.
*
* @param value the value to be added to this set.
* @return <code>true</code> if this set did not already contain the
* specified element.
* @throws NullPointerException if the value is <code>null</code>.
*/
public final boolean add(Object/*{E}*/ value) {
return _map.put(value, value) == null;
}
/**
* Returns an iterator over the elements in this set
* (allocated on the stack when executed in a
* {@link javolution.context.StackContext StackContext}).
*
* @return an iterator over this set values.
*/
public Iterator/*<E>*/iterator() {
return _map.keySet().iterator();
}
// Overrides to return a set (JDK1.5+).
public Collection/*Set<E>*/unmodifiable() {
return (Collection/*Set<E>*/) super.unmodifiable();
}
// Overrides (optimization).
public final void clear() {
_map.clear();
}
// Overrides (optimization).
public final boolean contains(Object o) {
return _map.containsKey(o);
}
// Overrides (optimization).
public final boolean remove(Object o) {
return _map.remove(o) != null;
}
/**
* Sets the comparator to use for value equality.
*
* @param comparator the value comparator.
* @return <code>this</code>
*/
public FastSet/*<E>*/ setValueComparator(FastComparator/*<? super E>*/ comparator) {
_map.setKeyComparator(comparator);
return this;
}
// Overrides.
public FastComparator/*<? super E>*/ getValueComparator() {
return _map.getKeyComparator();
}
// Implements Reusable.
public void reset() {
_map.reset();
}
// Requires special handling during de-serialization process.
private void readObject(ObjectInputStream stream) throws IOException,
ClassNotFoundException {
FastComparator cmp = (FastComparator) stream.readObject();
final int size = stream.readInt();
_map = new FastMap(size);
this.setValueComparator(cmp);
for (int i = size; i-- != 0;) {
Object key = stream.readObject();
_map.put(key, key);
}
}
// Requires special handling during serialization process.
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.writeObject(getValueComparator());
stream.writeInt(size());
for (FastMap.Entry e = _map.head(), end = _map.tail();
(e = (FastMap.Entry) e.getNext()) != end;) {
stream.writeObject(e.getKey());
}
}
// Implements FastCollection abstract method.
public final Record head() {
return _map.head();
}
// Implements FastCollection abstract method.
public final Record tail() {
return _map.tail();
}
// Implements FastCollection abstract method.
public final Object/*{E}*/ valueOf(Record record) {
return (Object/*{E}*/) ((FastMap.Entry) record).getKey();
}
// Implements FastCollection abstract method.
public final void delete(Record record) {
_map.remove(((FastMap.Entry) record).getKey());
}
private static final long serialVersionUID = 1L;
}