ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166x/ConcurrentSkipListSet.java
Revision: 1.17
Committed: Wed Jan 16 00:51:11 2013 UTC (11 years, 3 months ago) by jsr166
Branch: MAIN
Changes since 1.16: +64 -64 lines
Log Message:
<tt> -> {@code

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 jsr166 1.16 * used.
19 dl 1.1 *
20 jsr166 1.16 * <p>This implementation provides expected average <i>log(n)</i> time
21 jsr166 1.17 * cost for the {@code contains}, {@code add}, and {@code remove}
22 dl 1.1 * 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 jsr166 1.17 * <p>Beware that, unlike in most collections, the {@code size}
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 jsr166 1.17 * bulk operations {@code addAll}, {@code removeAll},
35     * <{@code retainAll}, and tt>containsAll</tt> are <em>not</em>
36 dl 1.4 * guaranteed to be performed atomically. For example, an iterator
37 jsr166 1.17 * operating concurrently with an {@code addAll} operation might view
38 dl 1.4 * 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 jsr166 1.17 * this class does not permit the use of {@code null} elements.
44     * because {@code null} 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 jsr166 1.17 * {@code null} value indicates that the elements' <i>natural
79 dl 1.1 * 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 jsr166 1.15 * @param c The elements that will comprise the new set
90 dl 1.1 *
91     * @throws ClassCastException if the elements in the specified
92 jsr166 1.15 * collection are not comparable, or are not mutually comparable
93 dl 1.4 * @throws NullPointerException if the specified collection is
94 jsr166 1.17 * {@code null}
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 jsr166 1.15 * @param s sorted set whose elements will comprise the new set
106 dl 1.4 * @throws NullPointerException if the specified sorted set is
107 jsr166 1.17 * {@code null}
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 jsr166 1.15 * @return a shallow copy of this set
119 dl 1.1 */
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 jsr166 1.17 * contains more than {@code Integer.MAX_VALUE} elements, it
138     * returns {@code Integer.MAX_VALUE}.
139 dl 1.1 *
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 jsr166 1.15 * @return the number of elements in this set
150 dl 1.1 */
151     public int size() {
152 jsr166 1.8 return m.size();
153 dl 1.1 }
154    
155     /**
156 jsr166 1.17 * Returns {@code true} if this set contains no elements.
157     * @return {@code true} if this set contains no elements
158 dl 1.1 */
159     public boolean isEmpty() {
160 jsr166 1.8 return m.isEmpty();
161 dl 1.1 }
162    
163     /**
164 jsr166 1.17 * Returns {@code true} if this set contains the specified element.
165 dl 1.1 *
166 jsr166 1.15 * @param o the object to be checked for containment in this set
167 jsr166 1.17 * @return {@code true} if this set contains the specified element
168 dl 1.1 *
169     * @throws ClassCastException if the specified object cannot be compared
170 jsr166 1.15 * with the elements currently in the set
171 jsr166 1.17 * @throws NullPointerException if o is {@code null}
172 dl 1.1 */
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 jsr166 1.15 * @param o element to be added to this set
181 jsr166 1.17 * @return {@code true} if the set did not already contain the specified
182 jsr166 1.15 * element
183 dl 1.1 *
184     * @throws ClassCastException if the specified object cannot be compared
185 jsr166 1.15 * with the elements currently in the set
186 jsr166 1.17 * @throws NullPointerException if o is {@code null}
187 dl 1.1 */
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 jsr166 1.15 * @param o object to be removed from this set, if present
196 jsr166 1.17 * @return {@code true} if the set contained the specified element
197 dl 1.1 *
198     * @throws ClassCastException if the specified object cannot be compared
199 jsr166 1.15 * with the elements currently in the set
200 jsr166 1.17 * @throws NullPointerException if o is {@code null}
201 dl 1.1 */
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 jsr166 1.15 * @return an iterator over the elements in this set
218 dl 1.1 */
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 jsr166 1.15 * @return an iterator over the elements in this set
228 dl 1.5 */
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 jsr166 1.17 * {@code true} if the specified object is also a set, the two sets
238 dl 1.4 * 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 jsr166 1.15 * @param o Object to be compared for equality with this set
245 jsr166 1.17 * @return {@code true} if the specified Object is equal to this set
246 dl 1.4 */
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 jsr166 1.15 * this set
271 jsr166 1.17 * @return {@code true} 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 jsr166 1.17 * of its elements are {@code null}
277 dl 1.4 */
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 jsr166 1.17 * {@code null} 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 jsr166 1.17 * {@code null} if there is no such element
296 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
297 jsr166 1.15 * currently in the set
298 jsr166 1.17 * @throws NullPointerException if o is {@code null}
299 dl 1.1 */
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 jsr166 1.17 * {@code null} 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 jsr166 1.17 * {@code null} if there is no such element
311 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
312 jsr166 1.15 * currently in the set
313 jsr166 1.17 * @throws NullPointerException if o is {@code null}
314 dl 1.1 */
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 jsr166 1.17 * {@code null} 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 jsr166 1.17 * element, or {@code null} if there is no such element
326 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
327 jsr166 1.15 * currently in the set
328 jsr166 1.17 * @throws NullPointerException if o is {@code null}
329 dl 1.1 */
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 jsr166 1.17 * {@code null} 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 jsr166 1.17 * {@code null} if there is no such element
341 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
342 jsr166 1.15 * currently in the set
343 jsr166 1.17 * @throws NullPointerException if o is {@code null}
344 dl 1.1 */
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 jsr166 1.17 * @return the least element, or {@code null} if empty
353 dl 1.2 */
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 jsr166 1.17 * @return the last element, or {@code null} if empty
362 dl 1.2 */
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 jsr166 1.17 * Returns the comparator used to order this set, or {@code null}
373 dl 1.1 * if this set uses its elements natural ordering.
374     *
375 jsr166 1.17 * @return the comparator used to order this set, or {@code null}
376 jsr166 1.15 * if this set uses its elements natural ordering
377 dl 1.1 */
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 jsr166 1.15 * @return the first (lowest) element currently in this set
386     * @throws NoSuchElementException sorted set is empty
387 dl 1.1 */
388     public E first() {
389     return m.firstKey();
390     }
391    
392     /**
393     * Returns the last (highest) element currently in this set.
394     *
395 jsr166 1.15 * @return the last (highest) element currently in this set
396     * @throws NoSuchElementException sorted set is empty
397 dl 1.1 */
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 jsr166 1.17 * {@code fromElement}, inclusive, to {@code toElement}, exclusive. (If
407     * {@code fromElement} and {@code toElement} are equal, the returned
408 dl 1.1 * 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 jsr166 1.15 * @param fromElement low endpoint (inclusive) of the subSet
412     * @param toElement high endpoint (exclusive) of the subSet
413 dl 1.1 * @return a view of the portion of this set whose elements range from
414 jsr166 1.17 * {@code fromElement}, inclusive, to {@code toElement},
415 jsr166 1.15 * exclusive
416 jsr166 1.17 * @throws ClassCastException if {@code fromElement} and
417     * {@code toElement} cannot be compared to one another using
418 dl 1.1 * this set's comparator (or, if the set has no comparator,
419 jsr166 1.15 * using natural ordering)
420 jsr166 1.17 * @throws IllegalArgumentException if {@code fromElement} is
421     * greater than {@code toElement}
422     * @throws NullPointerException if {@code fromElement} or
423     * {@code toElement} is {@code null}
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 jsr166 1.17 * less than {@code toElement}. The returned sorted set is backed by
432 dl 1.1 * this set, so changes in the returned sorted set are reflected in this
433 jsr166 1.7 * set, and vice-versa.
434 jsr166 1.15 * @param toElement high endpoint (exclusive) of the headSet
435 dl 1.1 * @return a view of the portion of this set whose elements are strictly
436 jsr166 1.15 * less than toElement
437 jsr166 1.17 * @throws ClassCastException if {@code toElement} is not compatible
438 dl 1.1 * with this set's comparator (or, if the set has no comparator,
439 jsr166 1.17 * if {@code toElement} does not implement {@code Comparable})
440     * @throws NullPointerException if {@code toElement} is {@code null}
441 dl 1.1 */
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 jsr166 1.17 * greater than or equal to {@code fromElement}. The returned
450 dl 1.1 * sorted set is backed by this set, so changes in the returned
451     * sorted set are reflected in this set, and vice-versa.
452 jsr166 1.15 * @param fromElement low endpoint (inclusive) of the tailSet
453 dl 1.1 * @return a view of the portion of this set whose elements are
454 jsr166 1.17 * greater than or equal to {@code fromElement}
455     * @throws ClassCastException if {@code fromElement} is not
456 dl 1.1 * compatible with this set's comparator (or, if the set has no
457 jsr166 1.17 * comparator, if {@code fromElement} does not implement
458     * {@code Comparable})
459     * @throws NullPointerException if {@code fromElement} is {@code null}
460 dl 1.1 */
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 jsr166 1.17 * constructed only using the {@code subSet}, {@code headSet}, and
473     * {@code tailSet} methods of their underlying sets.
474 dl 1.2 */
475 jsr166 1.7 static class ConcurrentSkipListSubSet<E>
476     extends AbstractSet<E>
477 dl 1.2 implements NavigableSet<E>, java.io.Serializable {
478    
479     private static final long serialVersionUID = -7647078645896651609L;
480    
481 dl 1.5 /** The underlying submap */
482 dl 1.2 private final ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object> s;
483 jsr166 1.7
484 dl 1.2 /**
485 jsr166 1.7 * Creates a new submap.
486 jsr166 1.17 * @param fromElement inclusive least value, or {@code null} if from start
487     * @param toElement exclusive upper bound or {@code null} if to end
488 dl 1.2 * @throws IllegalArgumentException if fromElement and toElement
489 jsr166 1.10 * non-null and fromElement greater than toElement
490 dl 1.2 */
491 jsr166 1.7 ConcurrentSkipListSubSet(ConcurrentSkipListMap<E,Object> map,
492 dl 1.2 E fromElement, E toElement) {
493 dl 1.5 s = new ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object>
494     (map, fromElement, toElement);
495 dl 1.2 }
496    
497 dl 1.5 // subsubset construction
498 dl 1.2
499 dl 1.5 public NavigableSet<E> subSet(E fromElement, E toElement) {
500 dl 1.2 if (!s.inOpenRange(fromElement) || !s.inOpenRange(toElement))
501     throw new IllegalArgumentException("element out of range");
502 jsr166 1.7 return new ConcurrentSkipListSubSet<E>(s.getMap(),
503 dl 1.2 fromElement, toElement);
504     }
505    
506     public NavigableSet<E> headSet(E toElement) {
507     E least = s.getLeast();
508     if (!s.inOpenRange(toElement))
509     throw new IllegalArgumentException("element out of range");
510 jsr166 1.7 return new ConcurrentSkipListSubSet<E>(s.getMap(),
511 dl 1.2 least, toElement);
512     }
513 jsr166 1.7
514 dl 1.2 public NavigableSet<E> tailSet(E fromElement) {
515     E fence = s.getFence();
516     if (!s.inOpenRange(fromElement))
517     throw new IllegalArgumentException("element out of range");
518 jsr166 1.7 return new ConcurrentSkipListSubSet<E>(s.getMap(),
519 dl 1.2 fromElement, fence);
520     }
521 dl 1.5
522     // relays to submap methods
523    
524     public int size() { return s.size(); }
525     public boolean isEmpty() { return s.isEmpty(); }
526     public boolean contains(Object o) { return s.containsKey(o); }
527     public void clear() { s.clear(); }
528     public E first() { return s.firstKey(); }
529     public E last() { return s.lastKey(); }
530     public E ceiling(E o) { return s.ceilingKey(o); }
531     public E lower(E o) { return s.lowerKey(o); }
532     public E floor(E o) { return s.floorKey(o); }
533     public E higher(E o) { return s.higherKey(o); }
534     public boolean remove(Object o) { return s.remove(o)==Boolean.TRUE; }
535     public boolean add(E o) { return s.put(o, Boolean.TRUE)==null; }
536     public Comparator<? super E> comparator() { return s.comparator(); }
537     public Iterator<E> iterator() { return s.keySet().iterator(); }
538     public Iterator<E> descendingIterator() {
539     return s.descendingKeySet().iterator();
540     }
541 jsr166 1.7 public E pollFirst() {
542 dl 1.5 Map.Entry<E,?> e = s.pollFirstEntry();
543 jsr166 1.11 return (e == null) ? null : e.getKey();
544 dl 1.5 }
545     public E pollLast() {
546     Map.Entry<E,?> e = s.pollLastEntry();
547 jsr166 1.11 return (e == null) ? null : e.getKey();
548 dl 1.5 }
549    
550 dl 1.2 }
551 jsr166 1.7 }