ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166x/ConcurrentSkipListSet.java
Revision: 1.19
Committed: Tue Feb 5 20:09:33 2013 UTC (11 years, 2 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.18: +1 -1 lines
Log Message:
give that javadoc some commas

File Contents

# Content
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/publicdomain/zero/1.0/
5 */
6
7 package jsr166x;
8
9 import java.util.*;
10 import java.util.concurrent.*;
11
12 /**
13 * 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.
19 *
20 * <p>This implementation provides expected average <i>log(n)</i> time
21 * cost for the {@code contains}, {@code add}, and {@code remove}
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 proceed concurrently with
28 * other operations.
29 *
30 * <p>Beware that, unlike in most collections, the {@code size}
31 * method is <em>not</em> a constant-time operation. Because of the
32 * asynchronous nature of these sets, determining the current number
33 * of elements requires a traversal of the elements. Additionally, the
34 * bulk operations {@code addAll}, {@code removeAll},
35 * {@code retainAll}, and {@code containsAll} are <em>not</em>
36 * guaranteed to be performed atomically. For example, an iterator
37 * operating concurrently with an {@code addAll} operation might view
38 * only some of the added elements.
39 *
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 {@code null} elements.
44 * because {@code null} arguments and return values cannot be reliably
45 * 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 implements NavigableSet<E>, Cloneable, java.io.Serializable {
53
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 private final ConcurrentSkipListMap<E,Object> m;
64
65 /**
66 * Constructs a new, empty set, sorted according to the elements' natural
67 * order.
68 */
69 public ConcurrentSkipListSet() {
70 m = new ConcurrentSkipListMap<E,Object>();
71 }
72
73 /**
74 * Constructs a new, empty set, sorted according to the specified
75 * comparator.
76 *
77 * @param c the comparator that will be used to sort this set. A
78 * {@code null} 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 * @throws NullPointerException if the specified collection is
94 * {@code null}
95 */
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 * @throws NullPointerException if the specified sorted set is
107 * {@code null}
108 */
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 try {
123 clone = (ConcurrentSkipListSet<E>) super.clone();
124 } catch (CloneNotSupportedException e) {
125 throw new InternalError();
126 }
127
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 {@code Integer.MAX_VALUE} elements, it
138 * returns {@code Integer.MAX_VALUE}.
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 return m.size();
153 }
154
155 /**
156 * Returns {@code true} if this set contains no elements.
157 * @return {@code true} if this set contains no elements
158 */
159 public boolean isEmpty() {
160 return m.isEmpty();
161 }
162
163 /**
164 * Returns {@code true} if this set contains the specified element.
165 *
166 * @param o the object to be checked for containment in this set
167 * @return {@code true} if this set contains the specified element
168 *
169 * @throws ClassCastException if the specified object cannot be compared
170 * with the elements currently in the set
171 * @throws NullPointerException if o is {@code null}
172 */
173 public boolean contains(Object o) {
174 return m.containsKey(o);
175 }
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 {@code true} if the set did not already contain the specified
182 * element
183 *
184 * @throws ClassCastException if the specified object cannot be compared
185 * with the elements currently in the set
186 * @throws NullPointerException if o is {@code null}
187 */
188 public boolean add(E o) {
189 return m.putIfAbsent(o, Boolean.TRUE) == null;
190 }
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 {@code true} if the set contained the specified element
197 *
198 * @throws ClassCastException if the specified object cannot be compared
199 * with the elements currently in the set
200 * @throws NullPointerException if o is {@code null}
201 */
202 public boolean remove(Object o) {
203 return m.removep(o);
204 }
205
206 /**
207 * Removes all of the elements from this set.
208 */
209 public void clear() {
210 m.clear();
211 }
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 return m.keyIterator();
221 }
222
223 /**
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 return m.descendingKeyIterator();
231 }
232
233 /* ---------------- AbstractSet Overrides -------------- */
234
235 /**
236 * Compares the specified object with this set for equality. Returns
237 * {@code true} 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 {@code true} 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 if (o == this)
250 return true;
251 if (!(o instanceof Set))
252 return false;
253 Collection c = (Collection) o;
254 try {
255 return containsAll(c) && c.containsAll(this);
256 } catch (ClassCastException unused) {
257 return false;
258 } catch (NullPointerException unused) {
259 return false;
260 }
261 }
262
263 /**
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 {@code true} if this set changed as a result of the call
272 *
273 * @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 {@code null}
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
287 /* ---------------- Relational operations -------------- */
288
289 /**
290 * Returns an element greater than or equal to the given element, or
291 * {@code null} if there is no such element.
292 *
293 * @param o the value to match
294 * @return an element greater than or equal to given element, or
295 * {@code null} if there is no such element
296 * @throws ClassCastException if o cannot be compared with the elements
297 * currently in the set
298 * @throws NullPointerException if o is {@code null}
299 */
300 public E ceiling(E o) {
301 return m.ceilingKey(o);
302 }
303
304 /**
305 * Returns an element strictly less than the given element, or
306 * {@code null} if there is no such element.
307 *
308 * @param o the value to match
309 * @return the greatest element less than the given element, or
310 * {@code null} if there is no such element
311 * @throws ClassCastException if o cannot be compared with the elements
312 * currently in the set
313 * @throws NullPointerException if o is {@code null}
314 */
315 public E lower(E o) {
316 return m.lowerKey(o);
317 }
318
319 /**
320 * Returns an element less than or equal to the given element, or
321 * {@code null} if there is no such element.
322 *
323 * @param o the value to match
324 * @return the greatest element less than or equal to given
325 * element, or {@code null} if there is no such element
326 * @throws ClassCastException if o cannot be compared with the elements
327 * currently in the set
328 * @throws NullPointerException if o is {@code null}
329 */
330 public E floor(E o) {
331 return m.floorKey(o);
332 }
333
334 /**
335 * Returns an element strictly greater than the given element, or
336 * {@code null} if there is no such element.
337 *
338 * @param o the value to match
339 * @return the least element greater than the given element, or
340 * {@code null} if there is no such element
341 * @throws ClassCastException if o cannot be compared with the elements
342 * currently in the set
343 * @throws NullPointerException if o is {@code null}
344 */
345 public E higher(E o) {
346 return m.higherKey(o);
347 }
348
349 /**
350 * Retrieves and removes the first (lowest) element.
351 *
352 * @return the least element, or {@code null} if empty
353 */
354 public E pollFirst() {
355 return m.pollFirstKey();
356 }
357
358 /**
359 * Retrieves and removes the last (highest) element.
360 *
361 * @return the last element, or {@code null} if empty
362 */
363 public E pollLast() {
364 return m.pollLastKey();
365 }
366
367
368 /* ---------------- SortedSet operations -------------- */
369
370
371 /**
372 * Returns the comparator used to order this set, or {@code null}
373 * if this set uses its elements natural ordering.
374 *
375 * @return the comparator used to order this set, or {@code null}
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
403
404 /**
405 * Returns a view of the portion of this set whose elements range from
406 * {@code fromElement}, inclusive, to {@code toElement}, exclusive. (If
407 * {@code fromElement} and {@code toElement} 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 * vice-versa.
411 * @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 * {@code fromElement}, inclusive, to {@code toElement},
415 * exclusive
416 * @throws ClassCastException if {@code fromElement} and
417 * {@code toElement} 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 {@code fromElement} is
421 * greater than {@code toElement}
422 * @throws NullPointerException if {@code fromElement} or
423 * {@code toElement} is {@code null}
424 */
425 public NavigableSet<E> subSet(E fromElement, E toElement) {
426 return new ConcurrentSkipListSubSet<E>(m, fromElement, toElement);
427 }
428
429 /**
430 * Returns a view of the portion of this set whose elements are strictly
431 * less than {@code toElement}. The returned sorted set is backed by
432 * this set, so changes in the returned sorted set are reflected in this
433 * set, and vice-versa.
434 * @param toElement high endpoint (exclusive) of the headSet
435 * @return a view of the portion of this set whose elements are strictly
436 * less than toElement
437 * @throws ClassCastException if {@code toElement} is not compatible
438 * with this set's comparator (or, if the set has no comparator,
439 * if {@code toElement} does not implement {@code Comparable})
440 * @throws NullPointerException if {@code toElement} is {@code null}
441 */
442 public NavigableSet<E> headSet(E toElement) {
443 return new ConcurrentSkipListSubSet<E>(m, null, toElement);
444 }
445
446
447 /**
448 * Returns a view of the portion of this set whose elements are
449 * greater than or equal to {@code fromElement}. 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 {@code fromElement}
455 * @throws ClassCastException if {@code fromElement} is not
456 * compatible with this set's comparator (or, if the set has no
457 * comparator, if {@code fromElement} does not implement
458 * {@code Comparable})
459 * @throws NullPointerException if {@code fromElement} is {@code null}
460 */
461 public NavigableSet<E> tailSet(E fromElement) {
462 return new ConcurrentSkipListSubSet<E>(m, fromElement, null);
463 }
464
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 {@code subSet}, {@code headSet}, and
473 * {@code tailSet} methods of their underlying sets.
474 */
475 static class ConcurrentSkipListSubSet<E>
476 extends AbstractSet<E>
477 implements NavigableSet<E>, java.io.Serializable {
478
479 private static final long serialVersionUID = -7647078645896651609L;
480
481 /** The underlying submap */
482 private final ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object> s;
483
484 /**
485 * Creates a new submap.
486 * @param fromElement inclusive least value, or {@code null} if from start
487 * @param toElement exclusive upper bound, or {@code null} if to end
488 * @throws IllegalArgumentException if fromElement and toElement
489 * non-null and fromElement greater than toElement
490 */
491 ConcurrentSkipListSubSet(ConcurrentSkipListMap<E,Object> map,
492 E fromElement, E toElement) {
493 s = new ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object>
494 (map, fromElement, toElement);
495 }
496
497 // subsubset construction
498
499 public NavigableSet<E> subSet(E fromElement, E toElement) {
500 if (!s.inOpenRange(fromElement) || !s.inOpenRange(toElement))
501 throw new IllegalArgumentException("element out of range");
502 return new ConcurrentSkipListSubSet<E>(s.getMap(),
503 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 return new ConcurrentSkipListSubSet<E>(s.getMap(),
511 least, toElement);
512 }
513
514 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 return new ConcurrentSkipListSubSet<E>(s.getMap(),
519 fromElement, fence);
520 }
521
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 public E pollFirst() {
542 Map.Entry<E,?> e = s.pollFirstEntry();
543 return (e == null) ? null : e.getKey();
544 }
545 public E pollLast() {
546 Map.Entry<E,?> e = s.pollLastEntry();
547 return (e == null) ? null : e.getKey();
548 }
549
550 }
551 }