ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166x/ConcurrentSkipListSet.java
Revision: 1.1
Committed: Wed Aug 11 10:58:15 2004 UTC (19 years, 8 months ago) by dl
Branch: MAIN
Log Message:
Initial checkin of initial jsr166x package and skip list classes

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/licenses/publicdomain
5     */
6    
7     package jsr166x;
8    
9     import java.util.*;
10     import java.util.concurrent.*;
11    
12     /**
13     * A scalable concurrent {@link SortedSet} and (priority) {@link
14     * Queue} implementation based on a {@link ConcurrentSkipListMap}.
15     * This class maintains a set in ascending order, sorted according to
16     * the <i>natural order</i> for the element's class (see {@link
17     * Comparable}), or by the comparator provided at creation time,
18     * depending on which constructor is used.<p>
19     *
20     * This implementation provides expected average <i>log(n)</i> time
21     * cost for the <tt>contains</tt>, <tt>add</tt>, and <tt>remove</tt>
22     * operations and their variants. Insertion, removal, and access
23     * operations safely execute concurrently by multiple
24     * threads. Iterators are <i>weakly consistent</i>, returning elements
25     * reflecting the state of the set at some point at or since the
26     * creation of the iterator. They do <em>not</em> throw {@link
27     * ConcurrentModificationException}, and may procede concurrently with
28     * other operations.
29     *
30     * <p>This class provides extended <tt>SortedSet</tt> methods
31     * searching for closest matches. Methods <tt>lower</tt>,
32     * <tt>floor</tt>, <tt>ceiling</tt>, and <tt>higher</tt> return
33     * elements respectively less, less than or equal, greater than or
34     * equal, and greater than a given value, returning null if there is
35     * no such element. These methods are designed for locating, not
36     * traversing entries. To traverse, use iterators and/or
37     * <tt>subset</tt>.
38     *
39     * <p>The class additionally supports {@link Queue} methods such as
40     * <tt>poll</tt> that atomically returns and removes the first
41     * element, if one exists. Thus, this class can serve as a priority
42     * queue in which there are no duplicate elements.
43     *
44     * <p>The {@link ConcurrentSkipListSubSet} objects returned by methods
45     * <tt>subset</tt>, <tt>headSet</tt>, and <tt>tailSet</tt> support the
46     * same extended set of operations as this class, but operate on their
47     * designated subrange of elements.
48     *
49     * <p>Beware that, unlike in most collections, the <tt>size</tt>
50     * method is <em>NOT</em> a constant-time operation. Because of the
51     * asynchronous nature of these sets, determining the current number
52     * of elements requires a traversal of the elements.
53     *
54     * <p>This class and its iterators implement all of the
55     * <em>optional</em> methods of the {@link Set} and {@link Iterator}
56     * interfaces. Like most other concurrent collection implementations,
57     * this class does not permit the use of <tt>null</tt> elements.
58     * because null arguments and return values cannot be reliably
59     * distinguished from the absence of elements.
60     *
61     * @author Doug Lea
62     * @param <E> the type of elements maintained by this set
63     */
64     public class ConcurrentSkipListSet<E>
65     extends AbstractSet<E>
66     implements SortedSet<E>, Queue<E>, Cloneable, java.io.Serializable {
67    
68     private static final long serialVersionUID = -2479143111061671589L;
69    
70     /**
71     * The underlying map. Uses Boolean.TRUE as value for each
72     * element. Note that this class relies on default serialization,
73     * which is a little wasteful in saving all of the useless value
74     * fields of underlying map, but enables this field to be declared
75     * final, which is necessary for thread safety.
76     */
77     private final ConcurrentSkipListMap<E,Object> m;
78    
79     /**
80     * Constructs a new, empty set, sorted according to the elements' natural
81     * order.
82     */
83     public ConcurrentSkipListSet() {
84     m = new ConcurrentSkipListMap<E,Object>();
85     }
86    
87     /**
88     * Constructs a new, empty set, sorted according to the specified
89     * comparator.
90     *
91     * @param c the comparator that will be used to sort this set. A
92     * <tt>null</tt> value indicates that the elements' <i>natural
93     * ordering</i> should be used.
94     */
95     public ConcurrentSkipListSet(Comparator<? super E> c) {
96     m = new ConcurrentSkipListMap<E,Object>(c);
97     }
98    
99     /**
100     * Constructs a new set containing the elements in the specified
101     * collection, sorted according to the elements' <i>natural order</i>.
102     *
103     * @param c The elements that will comprise the new set.
104     *
105     * @throws ClassCastException if the elements in the specified
106     * collection are not comparable, or are not mutually comparable.
107     * @throws NullPointerException if the specified collection is null.
108     */
109     public ConcurrentSkipListSet(Collection<? extends E> c) {
110     m = new ConcurrentSkipListMap<E,Object>();
111     addAll(c);
112     }
113    
114     /**
115     * Constructs a new set containing the same elements as the specified
116     * sorted set, sorted according to the same ordering.
117     *
118     * @param s sorted set whose elements will comprise the new set.
119     * @throws NullPointerException if the specified sorted set is null.
120     */
121     public ConcurrentSkipListSet(SortedSet<E> s) {
122     m = new ConcurrentSkipListMap<E,Object>(s.comparator());
123     addAll(s);
124     }
125    
126     /**
127     * Returns a shallow copy of this set. (The elements themselves
128     * are not cloned.)
129     *
130     * @return a shallow copy of this set.
131     */
132     public Object clone() {
133     ConcurrentSkipListSet<E> clone = null;
134     try {
135     clone = (ConcurrentSkipListSet<E>) super.clone();
136     } catch (CloneNotSupportedException e) {
137     throw new InternalError();
138     }
139    
140     clone.m.initialize();
141     clone.addAll(this);
142     return clone;
143     }
144    
145     /* ---------------- Set operations -------------- */
146    
147     /**
148     * Returns the number of elements in this set. If this set
149     * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
150     * returns <tt>Integer.MAX_VALUE</tt>.
151     *
152     * <p>Beware that, unlike in most collections, this method is
153     * <em>NOT</em> a constant-time operation. Because of the
154     * asynchronous nature of these sets, determining the current
155     * number of elements requires traversing them all to count them.
156     * Additionally, it is possible for the size to change during
157     * execution of this method, in which case the returned result
158     * will be inaccurate. Thus, this method is typically not very
159     * useful in concurrent applications.
160     *
161     * @return the number of elements in this set.
162     */
163     public int size() {
164     return m.size();
165     }
166    
167     /**
168     * Returns <tt>true</tt> if this set contains no elements.
169     * @return <tt>true</tt> if this set contains no elements.
170     */
171     public boolean isEmpty() {
172     return m.isEmpty();
173     }
174    
175     /**
176     * Returns <tt>true</tt> if this set contains the specified element.
177     *
178     * @param o the object to be checked for containment in this set.
179     * @return <tt>true</tt> if this set contains the specified element.
180     *
181     * @throws ClassCastException if the specified object cannot be compared
182     * with the elements currently in the set.
183     * @throws NullPointerException if o is <tt>null</tt>.
184     */
185     public boolean contains(Object o) {
186     return m.containsKey(o);
187     }
188    
189     /**
190     * Adds the specified element to this set if it is not already present.
191     *
192     * @param o element to be added to this set.
193     * @return <tt>true</tt> if the set did not already contain the specified
194     * element.
195     *
196     * @throws ClassCastException if the specified object cannot be compared
197     * with the elements currently in the set.
198     * @throws NullPointerException if o is <tt>null</tt>.
199     */
200     public boolean add(E o) {
201     return m.putIfAbsent(o, Boolean.TRUE) == null;
202     }
203    
204     /**
205     * Removes the specified element from this set if it is present.
206     *
207     * @param o object to be removed from this set, if present.
208     * @return <tt>true</tt> if the set contained the specified element.
209     *
210     * @throws ClassCastException if the specified object cannot be compared
211     * with the elements currently in the set.
212     * @throws NullPointerException if o is <tt>null</tt>.
213     */
214     public boolean remove(Object o) {
215     return m.removep(o);
216     }
217    
218     /**
219     * Removes all of the elements from this set.
220     */
221     public void clear() {
222     m.clear();
223     }
224    
225     /**
226     * Returns an iterator over the elements in this set. The elements
227     * are returned in ascending order.
228     *
229     * @return an iterator over the elements in this set.
230     */
231     public Iterator<E> iterator() {
232     return m.keyIterator();
233     }
234    
235     /* ---------------- Queue operations -------------- */
236    
237     /**
238     * Adds the specified element, or fails if this element is already
239     * present.
240     * @param o the element to insert.
241     * @return <tt>true</tt> if it was possible to add the element,
242     * else <tt>false</tt>
243     */
244     public boolean offer(E o) {
245     return add(o);
246     }
247    
248     /**
249     * Retrieves and removes the first (lowest) element.
250     *
251     * @return the least element, or <tt>null</tt> if empty.
252     */
253     public E poll() {
254     return m.removeFirstKey();
255     }
256    
257     /**
258     * Retrieves and removes the first (lowest) element. This method
259     * differs from the <tt>poll</tt> method in that it throws an
260     * exception if empty.
261     *
262     * @return the first (lowest) element.
263     * @throws NoSuchElementException if empty.
264     */
265     public E remove() {
266     E x = m.removeFirstKey();
267     if (x == null)
268     throw new NoSuchElementException();
269     return x;
270     }
271    
272     /**
273     * Retrieves, but does not remove, the first (lowest) element,
274     * returning <tt>null</tt> if empty.
275     *
276     * @return the first (lowest) element, or <tt>null</tt> if empty.
277     */
278     public E peek() {
279     return m.lowestKey();
280     }
281    
282     /**
283     * Retrieves, but does not remove, the first (lowest) element.
284     * This method differs from the <tt>peek</tt> method only in that
285     * it throws an exception if empty.
286     *
287     * @return the first (lowest) element.
288     * @throws NoSuchElementException if empty.
289     */
290     public E element() {
291     return m.firstKey();
292     }
293    
294     /* ---------------- Relational operations -------------- */
295    
296     /**
297     * Returns an element greater than or equal to the given element, or
298     * null if there is no such element.
299     *
300     * @param o the value to match
301     * @return an element greater than or equal to given element, or null
302     * if there is no such element.
303     * @throws ClassCastException if o cannot be compared with the elements
304     * currently in the set.
305     * @throws NullPointerException if o is <tt>null</tt>
306     */
307     public E ceiling(E o) {
308     return m.ceilingKey(o);
309     }
310    
311     /**
312     * Returns an element strictly less than the given element, or null if
313     * there is no such element.
314     *
315     * @param o the value to match
316     * @return the greatest element less than the given element, or
317     * null if there is no such element.
318     * @throws ClassCastException if o cannot be compared with the elements
319     * currently in the set.
320     * @throws NullPointerException if o is <tt>null</tt>.
321     */
322     public E lower(E o) {
323     return m.lowerKey(o);
324     }
325    
326     /**
327     * Returns an element less than or equal to the given element, or null
328     * if there is no such element.
329     *
330     * @param o the value to match
331     * @return the greatest element less than or equal to given
332     * element, or null if there is no such element.
333     * @throws ClassCastException if o cannot be compared with the elements
334     * currently in the set.
335     * @throws NullPointerException if o is <tt>null</tt>.
336     */
337     public E floor(E o) {
338     return m.floorKey(o);
339     }
340    
341     /**
342     * Returns an element strictly greater than the given element, or null
343     * if there is no such element.
344     *
345     * @param o the value to match
346     * @return the least element greater than the given element, or
347     * null if there is no such element.
348     * @throws ClassCastException if o cannot be compared with the elements
349     * currently in the set.
350     * @throws NullPointerException if o is <tt>null</tt>.
351     */
352     public E higher(E o) {
353     return m.higherKey(o);
354     }
355    
356     /* ---------------- SortedSet operations -------------- */
357    
358    
359     /**
360     * Returns the comparator used to order this set, or <tt>null</tt>
361     * if this set uses its elements natural ordering.
362     *
363     * @return the comparator used to order this set, or <tt>null</tt>
364     * if this set uses its elements natural ordering.
365     */
366     public Comparator<? super E> comparator() {
367     return m.comparator();
368     }
369    
370     /**
371     * Returns the first (lowest) element currently in this set.
372     *
373     * @return the first (lowest) element currently in this set.
374     * @throws NoSuchElementException sorted set is empty.
375     */
376     public E first() {
377     return m.firstKey();
378     }
379    
380     /**
381     * Returns the last (highest) element currently in this set.
382     *
383     * @return the last (highest) element currently in this set.
384     * @throws NoSuchElementException sorted set is empty.
385     */
386     public E last() {
387     return m.lastKey();
388     }
389    
390     /**
391     * Returns a view of the portion of this set whose elements range from
392     * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive. (If
393     * <tt>fromElement</tt> and <tt>toElement</tt> are equal, the returned
394     * sorted set is empty.) The returned sorted set is backed by this set,
395     * so changes in the returned sorted set are reflected in this set, and
396     * vice-versa.
397     * @param fromElement low endpoint (inclusive) of the subSet.
398     * @param toElement high endpoint (exclusive) of the subSet.
399     * @return a view of the portion of this set whose elements range from
400     * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
401     * exclusive.
402     * @throws ClassCastException if <tt>fromElement</tt> and
403     * <tt>toElement</tt> cannot be compared to one another using
404     * this set's comparator (or, if the set has no comparator,
405     * using natural ordering).
406     * @throws IllegalArgumentException if <tt>fromElement</tt> is
407     * greater than <tt>toElement</tt>.
408     * @throws NullPointerException if <tt>fromElement</tt> or
409     * <tt>toElement</tt> is <tt>null</tt>.
410     */
411     public ConcurrentSkipListSubSet<E> subSet(E fromElement, E toElement) {
412     return new ConcurrentSkipListSubSet<E>(m, fromElement, toElement);
413     }
414    
415     /**
416     * Returns a view of the portion of this set whose elements are strictly
417     * less than <tt>toElement</tt>. The returned sorted set is backed by
418     * this set, so changes in the returned sorted set are reflected in this
419     * set, and vice-versa.
420     * @param toElement high endpoint (exclusive) of the headSet.
421     * @return a view of the portion of this set whose elements are strictly
422     * less than toElement.
423     * @throws ClassCastException if <tt>toElement</tt> is not compatible
424     * with this set's comparator (or, if the set has no comparator,
425     * if <tt>toElement</tt> does not implement <tt>Comparable</tt>).
426     * @throws NullPointerException if <tt>toElement</tt> is <tt>null</tt>.
427     */
428     public ConcurrentSkipListSubSet<E> headSet(E toElement) {
429     return new ConcurrentSkipListSubSet<E>(m, null, toElement);
430     }
431    
432    
433     /**
434     * Returns a view of the portion of this set whose elements are
435     * greater than or equal to <tt>fromElement</tt>. The returned
436     * sorted set is backed by this set, so changes in the returned
437     * sorted set are reflected in this set, and vice-versa.
438     * @param fromElement low endpoint (inclusive) of the tailSet.
439     * @return a view of the portion of this set whose elements are
440     * greater than or equal to <tt>fromElement</tt>.
441     * @throws ClassCastException if <tt>fromElement</tt> is not
442     * compatible with this set's comparator (or, if the set has no
443     * comparator, if <tt>fromElement</tt> does not implement
444     * <tt>Comparable</tt>).
445     * @throws NullPointerException if <tt>fromElement</tt> is <tt>null</tt>.
446     */
447     public ConcurrentSkipListSubSet<E> tailSet(E fromElement) {
448     return new ConcurrentSkipListSubSet<E>(m, fromElement, null);
449     }
450     }