001: /*
002: * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
003: * Copyright (C) 2006 - Javolution (http://javolution.org/)
004: * All rights reserved.
005: *
006: * Permission to use, copy, modify, and distribute this software is
007: * freely granted, provided that this notice is preserved.
008: */
009: package javolution.util;
010:
011: import java.io.IOException;
012:
013: import j2me.io.ObjectInputStream;
014: import j2me.io.ObjectOutputStream;
015: import j2me.util.Collection;
016: import j2me.util.Iterator;
017: import j2me.util.Set;
018: import javolution.context.ObjectFactory;
019: import javolution.lang.Reusable;
020:
021: /**
022: * <p> This class represents a set collection backed by a {@link FastMap};
023: * smooth capacity increase and no rehashing ever performed.</p>
024: *
025: * <p> {@link FastSet}, as for any {@link FastCollection} sub-class, supports
026: * thread-safe fast iterations without using iterators. For example:[code]
027: * for (FastSet.Record r = set.head(), end = set.tail(); (r = r.getNext()) != end;) {
028: * Object value = set.valueOf(r);
029: * }[/code]</p>
030: *
031: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
032: * @version 4.2, December 18, 2006
033: */
034: public class FastSet/*<E>*/extends FastCollection/*<E>*/implements
035: Set/*<E>*/, Reusable {
036:
037: /**
038: * Holds the set factory.
039: */
040: private static final ObjectFactory FACTORY = new ObjectFactory() {
041:
042: public Object create() {
043: return new FastSet();
044: }
045:
046: public void cleanup(Object obj) {
047: ((FastSet) obj).reset();
048: }
049: };
050:
051: /**
052: * Holds the backing map.
053: */
054: private transient FastMap _map;
055:
056: /**
057: * Creates a set of small initial capacity.
058: */
059: public FastSet() {
060: this (new FastMap());
061: }
062:
063: /**
064: * Creates a persistent set associated to the specified unique identifier
065: * (convenience method).
066: *
067: * @param id the unique identifier for this map.
068: * @throws IllegalArgumentException if the identifier is not unique.
069: * @see javolution.context.PersistentContext.Reference
070: */
071: public FastSet(String id) {
072: this (new FastMap(id));
073: }
074:
075: /**
076: * Creates a set of specified initial capacity; unless the set size
077: * reaches the specified capacity, operations on this set will not allocate
078: * memory (no lazy object creation).
079: *
080: * @param capacity the initial capacity.
081: */
082: public FastSet(int capacity) {
083: this (new FastMap(capacity));
084: }
085:
086: /**
087: * Creates a set containing the specified elements, in the order they
088: * are returned by the set iterator.
089: *
090: * @param elements the elements to be placed into this fast set.
091: */
092: public FastSet(Set/*<? extends E>*/elements) {
093: this (new FastMap(elements.size()));
094: addAll(elements);
095: }
096:
097: /**
098: * Creates a set implemented using the specified map.
099: *
100: * @param map the backing map.
101: */
102: private FastSet(FastMap map) {
103: _map = map;
104: }
105:
106: /**
107: * Returns a new, preallocated or {@link #recycle recycled} set instance
108: * (on the stack when executing in a {@link javolution.context.StackContext
109: * StackContext}).
110: *
111: * @return a new, preallocated or recycled set instance.
112: */
113: public static/*<E>*/FastSet/*<E>*/newInstance() {
114: return (FastSet/*<E>*/) FACTORY.object();
115: }
116:
117: /**
118: * Recycles a set {@link #newInstance() instance} immediately
119: * (on the stack when executing in a {@link javolution.context.StackContext
120: * StackContext}).
121: */
122: public static void recycle(FastSet instance) {
123: FACTORY.recycle(instance);
124: }
125:
126: /**
127: * Returns the number of elements in this set (its cardinality).
128: *
129: * @return the number of elements in this set (its cardinality).
130: */
131: public final int size() {
132: return _map.size();
133: }
134:
135: /**
136: * Adds the specified value to this set if it is not already present.
137: *
138: * @param value the value to be added to this set.
139: * @return <code>true</code> if this set did not already contain the
140: * specified element.
141: * @throws NullPointerException if the value is <code>null</code>.
142: */
143: public final boolean add(Object/*{E}*/value) {
144: return _map.put(value, value) == null;
145: }
146:
147: /**
148: * Returns an iterator over the elements in this set
149: * (allocated on the stack when executed in a
150: * {@link javolution.context.StackContext StackContext}).
151: *
152: * @return an iterator over this set values.
153: */
154: public Iterator/*<E>*/iterator() {
155: return _map.keySet().iterator();
156: }
157:
158: // Overrides to return a set (JDK1.5+).
159: public Collection/*Set<E>*/unmodifiable() {
160: return (Collection/*Set<E>*/) super .unmodifiable();
161: }
162:
163: // Overrides (optimization).
164: public final void clear() {
165: _map.clear();
166: }
167:
168: // Overrides (optimization).
169: public final boolean contains(Object o) {
170: return _map.containsKey(o);
171: }
172:
173: // Overrides (optimization).
174: public final boolean remove(Object o) {
175: return _map.remove(o) != null;
176: }
177:
178: /**
179: * Sets the comparator to use for value equality.
180: *
181: * @param comparator the value comparator.
182: * @return <code>this</code>
183: */
184: public FastSet/*<E>*/setValueComparator(
185: FastComparator/*<? super E>*/comparator) {
186: _map.setKeyComparator(comparator);
187: return this ;
188: }
189:
190: // Overrides.
191: public FastComparator/*<? super E>*/getValueComparator() {
192: return _map.getKeyComparator();
193: }
194:
195: // Implements Reusable.
196: public void reset() {
197: _map.reset();
198: }
199:
200: // Requires special handling during de-serialization process.
201: private void readObject(ObjectInputStream stream)
202: throws IOException, ClassNotFoundException {
203: FastComparator cmp = (FastComparator) stream.readObject();
204: final int size = stream.readInt();
205: _map = new FastMap(size);
206: this .setValueComparator(cmp);
207: for (int i = size; i-- != 0;) {
208: Object key = stream.readObject();
209: _map.put(key, key);
210: }
211: }
212:
213: // Requires special handling during serialization process.
214: private void writeObject(ObjectOutputStream stream)
215: throws IOException {
216: stream.writeObject(getValueComparator());
217: stream.writeInt(size());
218: for (FastMap.Entry e = _map.head(), end = _map.tail(); (e = (FastMap.Entry) e
219: .getNext()) != end;) {
220: stream.writeObject(e.getKey());
221: }
222: }
223:
224: // Implements FastCollection abstract method.
225: public final Record head() {
226: return _map.head();
227: }
228:
229: // Implements FastCollection abstract method.
230: public final Record tail() {
231: return _map.tail();
232: }
233:
234: // Implements FastCollection abstract method.
235: public final Object/*{E}*/valueOf(Record record) {
236: return (Object/*{E}*/) ((FastMap.Entry) record).getKey();
237: }
238:
239: // Implements FastCollection abstract method.
240: public final void delete(Record record) {
241: _map.remove(((FastMap.Entry) record).getKey());
242: }
243:
244: private static final long serialVersionUID = 1L;
245: }
|