ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166x/ConcurrentSkipListSet.java
Revision: 1.6
Committed: Tue Mar 8 17:51:57 2005 UTC (19 years, 1 month ago) by dl
Branch: MAIN
Changes since 1.5: +1 -1 lines
Log Message:
Copyedit pass

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/licenses/publicdomain
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.<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 proceed concurrently with
28 * other operations.
29 *
30 * <p>Beware that, unlike in most collections, the <tt>size</tt>
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 <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 *
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 * because <tt>null</tt> 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 * <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 * @throws NullPointerException if the specified collection is
94 * <tt>null</tt>.
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 * <tt>null</tt>.
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 <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 return m.size();
153 }
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 return m.isEmpty();
161 }
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 * with the elements currently in the set.
171 * @throws NullPointerException if o is <tt>null</tt>.
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 <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 * with the elements currently in the set.
186 * @throws NullPointerException if o is <tt>null</tt>.
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 <tt>true</tt> 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 <tt>null</tt>.
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 * <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 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 <tt>true</tt> 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 <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
287 /* ---------------- Relational operations -------------- */
288
289 /**
290 * Returns an element greater than or equal to the given element, or
291 * <tt>null</tt> 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 * <tt>null</tt> 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 <tt>null</tt>
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 * <tt>null</tt> 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 * <tt>null</tt> 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 <tt>null</tt>.
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 * <tt>null</tt> 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 <tt>null</tt> 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 <tt>null</tt>.
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 * <tt>null</tt> 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 * <tt>null</tt> 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 <tt>null</tt>.
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 <tt>null</tt> 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 <tt>null</tt> 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 <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
403
404 /**
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 * 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 * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
415 * exclusive.
416 * @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 * <tt>toElement</tt> is <tt>null</tt>.
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 <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 * 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 <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 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 <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 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 <tt>subSet</tt>, <tt>headSet</tt>, and
473 * <tt>tailSet</tt> methods of their underlying sets.
474 *
475 */
476 static class ConcurrentSkipListSubSet<E>
477 extends AbstractSet<E>
478 implements NavigableSet<E>, java.io.Serializable {
479
480 private static final long serialVersionUID = -7647078645896651609L;
481
482 /** The underlying submap */
483 private final ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object> s;
484
485 /**
486 * Creates a new submap.
487 * @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 * @throws IllegalArgumentException if fromElement and toElement
490 * nonnull and fromElement greater than toElement
491 */
492 ConcurrentSkipListSubSet(ConcurrentSkipListMap<E,Object> map,
493 E fromElement, E toElement) {
494 s = new ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object>
495 (map, fromElement, toElement);
496 }
497
498 // subsubset construction
499
500 public NavigableSet<E> subSet(E fromElement, E toElement) {
501 if (!s.inOpenRange(fromElement) || !s.inOpenRange(toElement))
502 throw new IllegalArgumentException("element out of range");
503 return new ConcurrentSkipListSubSet<E>(s.getMap(),
504 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 return new ConcurrentSkipListSubSet<E>(s.getMap(),
512 least, toElement);
513 }
514
515 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 return new ConcurrentSkipListSubSet<E>(s.getMap(),
520 fromElement, fence);
521 }
522
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 public E pollFirst() {
543 Map.Entry<E,?> e = s.pollFirstEntry();
544 return (e == null)? null : e.getKey();
545 }
546 public E pollLast() {
547 Map.Entry<E,?> e = s.pollLastEntry();
548 return (e == null)? null : e.getKey();
549 }
550
551 }
552 }