ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166x/ConcurrentSkipListSet.java
Revision: 1.13
Committed: Mon Dec 19 19:18:36 2011 UTC (12 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.12: +1 -1 lines
Log Message:
whitespace

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 jsr166 1.12 * http://creativecommons.org/publicdomain/zero/1.0/
5 dl 1.1 */
6    
7 jsr166 1.7 package jsr166x;
8 dl 1.1
9     import java.util.*;
10     import java.util.concurrent.*;
11    
12     /**
13 dl 1.2 * A scalable concurrent {@link NavigableSet} implementation based on
14     * a {@link ConcurrentSkipListMap}. This class maintains a set in
15     * ascending order, sorted according to the <i>natural order</i> for
16     * the element's class (see {@link Comparable}), or by the comparator
17     * provided at creation time, depending on which constructor is
18     * used.<p>
19 dl 1.1 *
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 dl 1.6 * ConcurrentModificationException}, and may proceed concurrently with
28 dl 1.1 * other operations.
29     *
30     * <p>Beware that, unlike in most collections, the <tt>size</tt>
31 dl 1.4 * method is <em>not</em> a constant-time operation. Because of the
32 dl 1.1 * asynchronous nature of these sets, determining the current number
33 dl 1.4 * of elements requires a traversal of the elements. Additionally, the
34     * bulk operations <tt>addAll</tt>, <tt>removeAll</tt>,
35     * <<tt>retainAll</tt>, and tt>containsAll</tt> are <em>not</em>
36     * guaranteed to be performed atomically. For example, an iterator
37     * operating concurrently with an <tt>addAll</tt> operation might view
38     * only some of the added elements.
39 dl 1.1 *
40     * <p>This class and its iterators implement all of the
41     * <em>optional</em> methods of the {@link Set} and {@link Iterator}
42     * interfaces. Like most other concurrent collection implementations,
43     * this class does not permit the use of <tt>null</tt> elements.
44 dl 1.3 * because <tt>null</tt> arguments and return values cannot be reliably
45 dl 1.1 * distinguished from the absence of elements.
46     *
47     * @author Doug Lea
48     * @param <E> the type of elements maintained by this set
49     */
50     public class ConcurrentSkipListSet<E>
51     extends AbstractSet<E>
52 dl 1.2 implements NavigableSet<E>, Cloneable, java.io.Serializable {
53 dl 1.1
54     private static final long serialVersionUID = -2479143111061671589L;
55    
56     /**
57     * The underlying map. Uses Boolean.TRUE as value for each
58     * element. Note that this class relies on default serialization,
59     * which is a little wasteful in saving all of the useless value
60     * fields of underlying map, but enables this field to be declared
61     * final, which is necessary for thread safety.
62     */
63 jsr166 1.7 private final ConcurrentSkipListMap<E,Object> m;
64 dl 1.1
65     /**
66     * Constructs a new, empty set, sorted according to the elements' natural
67 jsr166 1.7 * order.
68 dl 1.1 */
69     public ConcurrentSkipListSet() {
70     m = new ConcurrentSkipListMap<E,Object>();
71     }
72    
73     /**
74     * Constructs a new, empty set, sorted according to the specified
75 jsr166 1.7 * comparator.
76 dl 1.1 *
77     * @param c the comparator that will be used to sort this set. A
78     * <tt>null</tt> value indicates that the elements' <i>natural
79     * ordering</i> should be used.
80     */
81     public ConcurrentSkipListSet(Comparator<? super E> c) {
82     m = new ConcurrentSkipListMap<E,Object>(c);
83     }
84    
85     /**
86     * Constructs a new set containing the elements in the specified
87     * collection, sorted according to the elements' <i>natural order</i>.
88     *
89     * @param c The elements that will comprise the new set.
90     *
91     * @throws ClassCastException if the elements in the specified
92     * collection are not comparable, or are not mutually comparable.
93 dl 1.4 * @throws NullPointerException if the specified collection is
94     * <tt>null</tt>.
95 dl 1.1 */
96     public ConcurrentSkipListSet(Collection<? extends E> c) {
97     m = new ConcurrentSkipListMap<E,Object>();
98     addAll(c);
99     }
100    
101     /**
102     * Constructs a new set containing the same elements as the specified
103     * sorted set, sorted according to the same ordering.
104     *
105     * @param s sorted set whose elements will comprise the new set.
106 dl 1.4 * @throws NullPointerException if the specified sorted set is
107     * <tt>null</tt>.
108 dl 1.1 */
109     public ConcurrentSkipListSet(SortedSet<E> s) {
110     m = new ConcurrentSkipListMap<E,Object>(s.comparator());
111     addAll(s);
112     }
113    
114     /**
115     * Returns a shallow copy of this set. (The elements themselves
116     * are not cloned.)
117     *
118     * @return a shallow copy of this set.
119     */
120     public Object clone() {
121     ConcurrentSkipListSet<E> clone = null;
122 jsr166 1.8 try {
123     clone = (ConcurrentSkipListSet<E>) super.clone();
124     } catch (CloneNotSupportedException e) {
125     throw new InternalError();
126     }
127 dl 1.1
128     clone.m.initialize();
129     clone.addAll(this);
130     return clone;
131     }
132    
133     /* ---------------- Set operations -------------- */
134    
135     /**
136     * Returns the number of elements in this set. If this set
137     * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
138     * returns <tt>Integer.MAX_VALUE</tt>.
139     *
140     * <p>Beware that, unlike in most collections, this method is
141     * <em>NOT</em> a constant-time operation. Because of the
142     * asynchronous nature of these sets, determining the current
143     * number of elements requires traversing them all to count them.
144     * Additionally, it is possible for the size to change during
145     * execution of this method, in which case the returned result
146     * will be inaccurate. Thus, this method is typically not very
147     * useful in concurrent applications.
148     *
149     * @return the number of elements in this set.
150     */
151     public int size() {
152 jsr166 1.8 return m.size();
153 dl 1.1 }
154    
155     /**
156     * Returns <tt>true</tt> if this set contains no elements.
157     * @return <tt>true</tt> if this set contains no elements.
158     */
159     public boolean isEmpty() {
160 jsr166 1.8 return m.isEmpty();
161 dl 1.1 }
162    
163     /**
164     * Returns <tt>true</tt> if this set contains the specified element.
165     *
166     * @param o the object to be checked for containment in this set.
167     * @return <tt>true</tt> if this set contains the specified element.
168     *
169     * @throws ClassCastException if the specified object cannot be compared
170 jsr166 1.8 * with the elements currently in the set.
171 dl 1.1 * @throws NullPointerException if o is <tt>null</tt>.
172     */
173     public boolean contains(Object o) {
174 jsr166 1.8 return m.containsKey(o);
175 dl 1.1 }
176    
177     /**
178     * Adds the specified element to this set if it is not already present.
179     *
180     * @param o element to be added to this set.
181     * @return <tt>true</tt> if the set did not already contain the specified
182     * element.
183     *
184     * @throws ClassCastException if the specified object cannot be compared
185 jsr166 1.8 * with the elements currently in the set.
186 dl 1.1 * @throws NullPointerException if o is <tt>null</tt>.
187     */
188     public boolean add(E o) {
189 jsr166 1.8 return m.putIfAbsent(o, Boolean.TRUE) == null;
190 dl 1.1 }
191    
192     /**
193     * Removes the specified element from this set if it is present.
194     *
195     * @param o object to be removed from this set, if present.
196     * @return <tt>true</tt> if the set contained the specified element.
197     *
198     * @throws ClassCastException if the specified object cannot be compared
199 jsr166 1.8 * with the elements currently in the set.
200 dl 1.1 * @throws NullPointerException if o is <tt>null</tt>.
201     */
202     public boolean remove(Object o) {
203 jsr166 1.8 return m.removep(o);
204 dl 1.1 }
205    
206     /**
207     * Removes all of the elements from this set.
208     */
209     public void clear() {
210 jsr166 1.8 m.clear();
211 dl 1.1 }
212    
213     /**
214     * Returns an iterator over the elements in this set. The elements
215     * are returned in ascending order.
216     *
217     * @return an iterator over the elements in this set.
218     */
219     public Iterator<E> iterator() {
220 jsr166 1.8 return m.keyIterator();
221 dl 1.1 }
222 dl 1.4
223 dl 1.5 /**
224     * Returns an iterator over the elements in this set. The elements
225     * are returned in descending order.
226     *
227     * @return an iterator over the elements in this set.
228     */
229     public Iterator<E> descendingIterator() {
230 jsr166 1.8 return m.descendingKeyIterator();
231 dl 1.5 }
232    
233 dl 1.4 /* ---------------- AbstractSet Overrides -------------- */
234    
235     /**
236     * Compares the specified object with this set for equality. Returns
237     * <tt>true</tt> if the specified object is also a set, the two sets
238     * have the same size, and every member of the specified set is
239     * contained in this set (or equivalently, every member of this set is
240     * contained in the specified set). This definition ensures that the
241     * equals method works properly across different implementations of the
242     * set interface.
243     *
244     * @param o Object to be compared for equality with this set.
245     * @return <tt>true</tt> if the specified Object is equal to this set.
246     */
247     public boolean equals(Object o) {
248     // Override AbstractSet version to avoid calling size()
249 jsr166 1.8 if (o == this)
250     return true;
251     if (!(o instanceof Set))
252     return false;
253     Collection c = (Collection) o;
254 dl 1.4 try {
255     return containsAll(c) && c.containsAll(this);
256 jsr166 1.13 } catch (ClassCastException unused) {
257 dl 1.4 return false;
258 jsr166 1.9 } catch (NullPointerException unused) {
259 dl 1.4 return false;
260     }
261     }
262 jsr166 1.7
263 dl 1.4 /**
264     * Removes from this set all of its elements that are contained in
265     * the specified collection. If the specified collection is also
266     * a set, this operation effectively modifies this set so that its
267     * value is the <i>asymmetric set difference</i> of the two sets.
268     *
269     * @param c collection that defines which elements will be removed from
270     * this set.
271     * @return <tt>true</tt> if this set changed as a result of the call.
272 jsr166 1.7 *
273 dl 1.4 * @throws ClassCastException if the types of one or more elements in this
274     * set are incompatible with the specified collection
275     * @throws NullPointerException if the specified collection, or any
276     * of its elements are <tt>null</tt>.
277     */
278     public boolean removeAll(Collection<?> c) {
279     // Override AbstractSet version to avoid unnecessary call to size()
280     boolean modified = false;
281     for (Iterator<?> i = c.iterator(); i.hasNext(); )
282     if (remove(i.next()))
283     modified = true;
284     return modified;
285     }
286 jsr166 1.7
287 dl 1.1 /* ---------------- Relational operations -------------- */
288    
289     /**
290     * Returns an element greater than or equal to the given element, or
291 dl 1.3 * <tt>null</tt> if there is no such element.
292 jsr166 1.7 *
293 dl 1.1 * @param o the value to match
294 dl 1.4 * @return an element greater than or equal to given element, or
295     * <tt>null</tt> if there is no such element.
296 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
297     * currently in the set.
298     * @throws NullPointerException if o is <tt>null</tt>
299     */
300     public E ceiling(E o) {
301     return m.ceilingKey(o);
302     }
303    
304     /**
305 dl 1.4 * Returns an element strictly less than the given element, or
306     * <tt>null</tt> if there is no such element.
307 jsr166 1.7 *
308 dl 1.1 * @param o the value to match
309     * @return the greatest element less than the given element, or
310 dl 1.3 * <tt>null</tt> if there is no such element.
311 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
312     * currently in the set.
313     * @throws NullPointerException if o is <tt>null</tt>.
314     */
315     public E lower(E o) {
316     return m.lowerKey(o);
317     }
318    
319     /**
320 dl 1.4 * Returns an element less than or equal to the given element, or
321     * <tt>null</tt> if there is no such element.
322 jsr166 1.7 *
323 dl 1.1 * @param o the value to match
324     * @return the greatest element less than or equal to given
325 dl 1.3 * element, or <tt>null</tt> if there is no such element.
326 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
327     * currently in the set.
328     * @throws NullPointerException if o is <tt>null</tt>.
329     */
330     public E floor(E o) {
331     return m.floorKey(o);
332     }
333    
334     /**
335 dl 1.4 * Returns an element strictly greater than the given element, or
336     * <tt>null</tt> if there is no such element.
337 jsr166 1.7 *
338 dl 1.1 * @param o the value to match
339     * @return the least element greater than the given element, or
340 dl 1.3 * <tt>null</tt> if there is no such element.
341 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
342     * currently in the set.
343     * @throws NullPointerException if o is <tt>null</tt>.
344     */
345     public E higher(E o) {
346     return m.higherKey(o);
347     }
348    
349 dl 1.2 /**
350     * Retrieves and removes the first (lowest) element.
351     *
352     * @return the least element, or <tt>null</tt> if empty.
353     */
354     public E pollFirst() {
355 dl 1.5 return m.pollFirstKey();
356 dl 1.2 }
357    
358     /**
359     * Retrieves and removes the last (highest) element.
360     *
361     * @return the last element, or <tt>null</tt> if empty.
362     */
363     public E pollLast() {
364 dl 1.5 return m.pollLastKey();
365 dl 1.2 }
366    
367    
368 dl 1.1 /* ---------------- SortedSet operations -------------- */
369    
370    
371     /**
372     * Returns the comparator used to order this set, or <tt>null</tt>
373     * if this set uses its elements natural ordering.
374     *
375     * @return the comparator used to order this set, or <tt>null</tt>
376     * if this set uses its elements natural ordering.
377     */
378     public Comparator<? super E> comparator() {
379     return m.comparator();
380     }
381    
382     /**
383     * Returns the first (lowest) element currently in this set.
384     *
385     * @return the first (lowest) element currently in this set.
386     * @throws NoSuchElementException sorted set is empty.
387     */
388     public E first() {
389     return m.firstKey();
390     }
391    
392     /**
393     * Returns the last (highest) element currently in this set.
394     *
395     * @return the last (highest) element currently in this set.
396     * @throws NoSuchElementException sorted set is empty.
397     */
398     public E last() {
399     return m.lastKey();
400     }
401    
402 dl 1.4
403    
404 dl 1.1 /**
405     * Returns a view of the portion of this set whose elements range from
406     * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive. (If
407     * <tt>fromElement</tt> and <tt>toElement</tt> are equal, the returned
408     * sorted set is empty.) The returned sorted set is backed by this set,
409     * so changes in the returned sorted set are reflected in this set, and
410 jsr166 1.7 * vice-versa.
411 dl 1.1 * @param fromElement low endpoint (inclusive) of the subSet.
412     * @param toElement high endpoint (exclusive) of the subSet.
413     * @return a view of the portion of this set whose elements range from
414 jsr166 1.8 * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
415     * exclusive.
416 dl 1.1 * @throws ClassCastException if <tt>fromElement</tt> and
417     * <tt>toElement</tt> cannot be compared to one another using
418     * this set's comparator (or, if the set has no comparator,
419     * using natural ordering).
420     * @throws IllegalArgumentException if <tt>fromElement</tt> is
421     * greater than <tt>toElement</tt>.
422     * @throws NullPointerException if <tt>fromElement</tt> or
423 jsr166 1.8 * <tt>toElement</tt> is <tt>null</tt>.
424 dl 1.1 */
425 dl 1.2 public NavigableSet<E> subSet(E fromElement, E toElement) {
426 jsr166 1.8 return new ConcurrentSkipListSubSet<E>(m, fromElement, toElement);
427 dl 1.1 }
428    
429     /**
430     * Returns a view of the portion of this set whose elements are strictly
431     * less than <tt>toElement</tt>. The returned sorted set is backed by
432     * this set, so changes in the returned sorted set are reflected in this
433 jsr166 1.7 * set, and vice-versa.
434 dl 1.1 * @param toElement high endpoint (exclusive) of the headSet.
435     * @return a view of the portion of this set whose elements are strictly
436 jsr166 1.8 * less than toElement.
437 dl 1.1 * @throws ClassCastException if <tt>toElement</tt> is not compatible
438     * with this set's comparator (or, if the set has no comparator,
439     * if <tt>toElement</tt> does not implement <tt>Comparable</tt>).
440     * @throws NullPointerException if <tt>toElement</tt> is <tt>null</tt>.
441     */
442 dl 1.2 public NavigableSet<E> headSet(E toElement) {
443 jsr166 1.8 return new ConcurrentSkipListSubSet<E>(m, null, toElement);
444 dl 1.1 }
445    
446    
447     /**
448     * Returns a view of the portion of this set whose elements are
449     * greater than or equal to <tt>fromElement</tt>. The returned
450     * sorted set is backed by this set, so changes in the returned
451     * sorted set are reflected in this set, and vice-versa.
452     * @param fromElement low endpoint (inclusive) of the tailSet.
453     * @return a view of the portion of this set whose elements are
454     * greater than or equal to <tt>fromElement</tt>.
455     * @throws ClassCastException if <tt>fromElement</tt> is not
456     * compatible with this set's comparator (or, if the set has no
457     * comparator, if <tt>fromElement</tt> does not implement
458     * <tt>Comparable</tt>).
459     * @throws NullPointerException if <tt>fromElement</tt> is <tt>null</tt>.
460     */
461 dl 1.2 public NavigableSet<E> tailSet(E fromElement) {
462 jsr166 1.8 return new ConcurrentSkipListSubSet<E>(m, fromElement, null);
463 dl 1.1 }
464 dl 1.2
465     /**
466     * Subsets returned by {@link ConcurrentSkipListSet} subset operations
467     * represent a subrange of elements of their underlying
468     * sets. Instances of this class support all methods of their
469     * underlying sets, differing in that elements outside their range are
470     * ignored, and attempts to add elements outside their ranges result
471     * in {@link IllegalArgumentException}. Instances of this class are
472     * constructed only using the <tt>subSet</tt>, <tt>headSet</tt>, and
473     * <tt>tailSet</tt> methods of their underlying sets.
474     *
475     */
476 jsr166 1.7 static class ConcurrentSkipListSubSet<E>
477     extends AbstractSet<E>
478 dl 1.2 implements NavigableSet<E>, java.io.Serializable {
479    
480     private static final long serialVersionUID = -7647078645896651609L;
481    
482 dl 1.5 /** The underlying submap */
483 dl 1.2 private final ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object> s;
484 jsr166 1.7
485 dl 1.2 /**
486 jsr166 1.7 * Creates a new submap.
487 dl 1.3 * @param fromElement inclusive least value, or <tt>null</tt> if from start
488     * @param toElement exclusive upper bound or <tt>null</tt> if to end
489 dl 1.2 * @throws IllegalArgumentException if fromElement and toElement
490 jsr166 1.10 * non-null and fromElement greater than toElement
491 dl 1.2 */
492 jsr166 1.7 ConcurrentSkipListSubSet(ConcurrentSkipListMap<E,Object> map,
493 dl 1.2 E fromElement, E toElement) {
494 dl 1.5 s = new ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object>
495     (map, fromElement, toElement);
496 dl 1.2 }
497    
498 dl 1.5 // subsubset construction
499 dl 1.2
500 dl 1.5 public NavigableSet<E> subSet(E fromElement, E toElement) {
501 dl 1.2 if (!s.inOpenRange(fromElement) || !s.inOpenRange(toElement))
502     throw new IllegalArgumentException("element out of range");
503 jsr166 1.7 return new ConcurrentSkipListSubSet<E>(s.getMap(),
504 dl 1.2 fromElement, toElement);
505     }
506    
507     public NavigableSet<E> headSet(E toElement) {
508     E least = s.getLeast();
509     if (!s.inOpenRange(toElement))
510     throw new IllegalArgumentException("element out of range");
511 jsr166 1.7 return new ConcurrentSkipListSubSet<E>(s.getMap(),
512 dl 1.2 least, toElement);
513     }
514 jsr166 1.7
515 dl 1.2 public NavigableSet<E> tailSet(E fromElement) {
516     E fence = s.getFence();
517     if (!s.inOpenRange(fromElement))
518     throw new IllegalArgumentException("element out of range");
519 jsr166 1.7 return new ConcurrentSkipListSubSet<E>(s.getMap(),
520 dl 1.2 fromElement, fence);
521     }
522 dl 1.5
523     // relays to submap methods
524    
525     public int size() { return s.size(); }
526     public boolean isEmpty() { return s.isEmpty(); }
527     public boolean contains(Object o) { return s.containsKey(o); }
528     public void clear() { s.clear(); }
529     public E first() { return s.firstKey(); }
530     public E last() { return s.lastKey(); }
531     public E ceiling(E o) { return s.ceilingKey(o); }
532     public E lower(E o) { return s.lowerKey(o); }
533     public E floor(E o) { return s.floorKey(o); }
534     public E higher(E o) { return s.higherKey(o); }
535     public boolean remove(Object o) { return s.remove(o)==Boolean.TRUE; }
536     public boolean add(E o) { return s.put(o, Boolean.TRUE)==null; }
537     public Comparator<? super E> comparator() { return s.comparator(); }
538     public Iterator<E> iterator() { return s.keySet().iterator(); }
539     public Iterator<E> descendingIterator() {
540     return s.descendingKeySet().iterator();
541     }
542 jsr166 1.7 public E pollFirst() {
543 dl 1.5 Map.Entry<E,?> e = s.pollFirstEntry();
544 jsr166 1.11 return (e == null) ? null : e.getKey();
545 dl 1.5 }
546     public E pollLast() {
547     Map.Entry<E,?> e = s.pollLastEntry();
548 jsr166 1.11 return (e == null) ? null : e.getKey();
549 dl 1.5 }
550    
551 dl 1.2 }
552 jsr166 1.7 }