ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentSkipListSet.java
Revision: 1.40
Committed: Thu Aug 8 15:13:34 2013 UTC (10 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.39: +18 -0 lines
Log Message:
add javadoc for spliterator()

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 java.util.concurrent;
8 import java.util.AbstractSet;
9 import java.util.Collection;
10 import java.util.Collections;
11 import java.util.Comparator;
12 import java.util.Iterator;
13 import java.util.Map;
14 import java.util.NavigableMap;
15 import java.util.NavigableSet;
16 import java.util.Set;
17 import java.util.SortedSet;
18 import java.util.Spliterator;
19 import java.util.stream.Stream;
20
21 /**
22 * A scalable concurrent {@link NavigableSet} implementation based on
23 * a {@link ConcurrentSkipListMap}. The elements of the set are kept
24 * sorted according to their {@linkplain Comparable natural ordering},
25 * or by a {@link Comparator} provided at set creation time, depending
26 * on which constructor is used.
27 *
28 * <p>This implementation provides expected average <i>log(n)</i> time
29 * cost for the {@code contains}, {@code add}, and {@code remove}
30 * operations and their variants. Insertion, removal, and access
31 * operations safely execute concurrently by multiple threads.
32 * Iterators are <i>weakly consistent</i>, returning elements
33 * reflecting the state of the set at some point at or since the
34 * creation of the iterator. They do <em>not</em> throw {@link
35 * java.util.ConcurrentModificationException}, and may proceed
36 * concurrently with other operations. Ascending ordered views and
37 * their iterators are faster than descending ones.
38 *
39 * <p>Beware that, unlike in most collections, the {@code size}
40 * method is <em>not</em> a constant-time operation. Because of the
41 * asynchronous nature of these sets, determining the current number
42 * of elements requires a traversal of the elements, and so may report
43 * inaccurate results if this collection is modified during traversal.
44 * Additionally, the bulk operations {@code addAll},
45 * {@code removeAll}, {@code retainAll}, {@code containsAll},
46 * {@code equals}, and {@code toArray} are <em>not</em> guaranteed
47 * to be performed atomically. For example, an iterator operating
48 * concurrently with an {@code addAll} operation might view only some
49 * of the added elements.
50 *
51 * <p>This class and its iterators implement all of the
52 * <em>optional</em> methods of the {@link Set} and {@link Iterator}
53 * interfaces. Like most other concurrent collection implementations,
54 * this class does not permit the use of {@code null} elements,
55 * because {@code null} arguments and return values cannot be reliably
56 * distinguished from the absence of elements.
57 *
58 * <p>This class is a member of the
59 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
60 * Java Collections Framework</a>.
61 *
62 * @author Doug Lea
63 * @param <E> the type of elements maintained by this set
64 * @since 1.6
65 */
66 public class ConcurrentSkipListSet<E>
67 extends AbstractSet<E>
68 implements NavigableSet<E>, Cloneable, java.io.Serializable {
69
70 private static final long serialVersionUID = -2479143111061671589L;
71
72 /**
73 * The underlying map. Uses Boolean.TRUE as value for each
74 * element. This field is declared final for the sake of thread
75 * safety, which entails some ugliness in clone().
76 */
77 private final ConcurrentNavigableMap<E,Object> m;
78
79 /**
80 * Constructs a new, empty set that orders its elements according to
81 * their {@linkplain Comparable natural ordering}.
82 */
83 public ConcurrentSkipListSet() {
84 m = new ConcurrentSkipListMap<E,Object>();
85 }
86
87 /**
88 * Constructs a new, empty set that orders its elements according to
89 * the specified comparator.
90 *
91 * @param comparator the comparator that will be used to order this set.
92 * If {@code null}, the {@linkplain Comparable natural
93 * ordering} of the elements will be used.
94 */
95 public ConcurrentSkipListSet(Comparator<? super E> comparator) {
96 m = new ConcurrentSkipListMap<E,Object>(comparator);
97 }
98
99 /**
100 * Constructs a new set containing the elements in the specified
101 * collection, that orders its elements according to their
102 * {@linkplain Comparable natural ordering}.
103 *
104 * @param c The elements that will comprise the new set
105 * @throws ClassCastException if the elements in {@code c} are
106 * not {@link Comparable}, or are not mutually comparable
107 * @throws NullPointerException if the specified collection or any
108 * of its elements are null
109 */
110 public ConcurrentSkipListSet(Collection<? extends E> c) {
111 m = new ConcurrentSkipListMap<E,Object>();
112 addAll(c);
113 }
114
115 /**
116 * Constructs a new set containing the same elements and using the
117 * same ordering as the specified sorted set.
118 *
119 * @param s sorted set whose elements will comprise the new set
120 * @throws NullPointerException if the specified sorted set or any
121 * of its elements are null
122 */
123 public ConcurrentSkipListSet(SortedSet<E> s) {
124 m = new ConcurrentSkipListMap<E,Object>(s.comparator());
125 addAll(s);
126 }
127
128 /**
129 * For use by submaps
130 */
131 ConcurrentSkipListSet(ConcurrentNavigableMap<E,Object> m) {
132 this.m = m;
133 }
134
135 /**
136 * Returns a shallow copy of this {@code ConcurrentSkipListSet}
137 * instance. (The elements themselves are not cloned.)
138 *
139 * @return a shallow copy of this set
140 */
141 public ConcurrentSkipListSet<E> clone() {
142 try {
143 @SuppressWarnings("unchecked")
144 ConcurrentSkipListSet<E> clone =
145 (ConcurrentSkipListSet<E>) super.clone();
146 clone.setMap(new ConcurrentSkipListMap<E,Object>(m));
147 return clone;
148 } catch (CloneNotSupportedException e) {
149 throw new InternalError();
150 }
151 }
152
153 /* ---------------- Set operations -------------- */
154
155 /**
156 * Returns the number of elements in this set. If this set
157 * contains more than {@code Integer.MAX_VALUE} elements, it
158 * returns {@code Integer.MAX_VALUE}.
159 *
160 * <p>Beware that, unlike in most collections, this method is
161 * <em>NOT</em> a constant-time operation. Because of the
162 * asynchronous nature of these sets, determining the current
163 * number of elements requires traversing them all to count them.
164 * Additionally, it is possible for the size to change during
165 * execution of this method, in which case the returned result
166 * will be inaccurate. Thus, this method is typically not very
167 * useful in concurrent applications.
168 *
169 * @return the number of elements in this set
170 */
171 public int size() {
172 return m.size();
173 }
174
175 /**
176 * Returns {@code true} if this set contains no elements.
177 * @return {@code true} if this set contains no elements
178 */
179 public boolean isEmpty() {
180 return m.isEmpty();
181 }
182
183 /**
184 * Returns {@code true} if this set contains the specified element.
185 * More formally, returns {@code true} if and only if this set
186 * contains an element {@code e} such that {@code o.equals(e)}.
187 *
188 * @param o object to be checked for containment in this set
189 * @return {@code true} if this set contains the specified element
190 * @throws ClassCastException if the specified element cannot be
191 * compared with the elements currently in this set
192 * @throws NullPointerException if the specified element is null
193 */
194 public boolean contains(Object o) {
195 return m.containsKey(o);
196 }
197
198 /**
199 * Adds the specified element to this set if it is not already present.
200 * More formally, adds the specified element {@code e} to this set if
201 * the set contains no element {@code e2} such that {@code e.equals(e2)}.
202 * If this set already contains the element, the call leaves the set
203 * unchanged and returns {@code false}.
204 *
205 * @param e element to be added to this set
206 * @return {@code true} if this set did not already contain the
207 * specified element
208 * @throws ClassCastException if {@code e} cannot be compared
209 * with the elements currently in this set
210 * @throws NullPointerException if the specified element is null
211 */
212 public boolean add(E e) {
213 return m.putIfAbsent(e, Boolean.TRUE) == null;
214 }
215
216 /**
217 * Removes the specified element from this set if it is present.
218 * More formally, removes an element {@code e} such that
219 * {@code o.equals(e)}, if this set contains such an element.
220 * Returns {@code true} if this set contained the element (or
221 * equivalently, if this set changed as a result of the call).
222 * (This set will not contain the element once the call returns.)
223 *
224 * @param o object to be removed from this set, if present
225 * @return {@code true} if this set contained the specified element
226 * @throws ClassCastException if {@code o} cannot be compared
227 * with the elements currently in this set
228 * @throws NullPointerException if the specified element is null
229 */
230 public boolean remove(Object o) {
231 return m.remove(o, Boolean.TRUE);
232 }
233
234 /**
235 * Removes all of the elements from this set.
236 */
237 public void clear() {
238 m.clear();
239 }
240
241 /**
242 * Returns an iterator over the elements in this set in ascending order.
243 *
244 * @return an iterator over the elements in this set in ascending order
245 */
246 public Iterator<E> iterator() {
247 return m.navigableKeySet().iterator();
248 }
249
250 /**
251 * Returns an iterator over the elements in this set in descending order.
252 *
253 * @return an iterator over the elements in this set in descending order
254 */
255 public Iterator<E> descendingIterator() {
256 return m.descendingKeySet().iterator();
257 }
258
259
260 /* ---------------- AbstractSet Overrides -------------- */
261
262 /**
263 * Compares the specified object with this set for equality. Returns
264 * {@code true} if the specified object is also a set, the two sets
265 * have the same size, and every member of the specified set is
266 * contained in this set (or equivalently, every member of this set is
267 * contained in the specified set). This definition ensures that the
268 * equals method works properly across different implementations of the
269 * set interface.
270 *
271 * @param o the object to be compared for equality with this set
272 * @return {@code true} if the specified object is equal to this set
273 */
274 public boolean equals(Object o) {
275 // Override AbstractSet version to avoid calling size()
276 if (o == this)
277 return true;
278 if (!(o instanceof Set))
279 return false;
280 Collection<?> c = (Collection<?>) o;
281 try {
282 return containsAll(c) && c.containsAll(this);
283 } catch (ClassCastException unused) {
284 return false;
285 } catch (NullPointerException unused) {
286 return false;
287 }
288 }
289
290 /**
291 * Removes from this set all of its elements that are contained in
292 * the specified collection. If the specified collection is also
293 * a set, this operation effectively modifies this set so that its
294 * value is the <i>asymmetric set difference</i> of the two sets.
295 *
296 * @param c collection containing elements to be removed from this set
297 * @return {@code true} if this set changed as a result of the call
298 * @throws ClassCastException if the types of one or more elements in this
299 * set are incompatible with the specified collection
300 * @throws NullPointerException if the specified collection or any
301 * of its elements are null
302 */
303 public boolean removeAll(Collection<?> c) {
304 // Override AbstractSet version to avoid unnecessary call to size()
305 boolean modified = false;
306 for (Object e : c)
307 if (remove(e))
308 modified = true;
309 return modified;
310 }
311
312 /* ---------------- Relational operations -------------- */
313
314 /**
315 * @throws ClassCastException {@inheritDoc}
316 * @throws NullPointerException if the specified element is null
317 */
318 public E lower(E e) {
319 return m.lowerKey(e);
320 }
321
322 /**
323 * @throws ClassCastException {@inheritDoc}
324 * @throws NullPointerException if the specified element is null
325 */
326 public E floor(E e) {
327 return m.floorKey(e);
328 }
329
330 /**
331 * @throws ClassCastException {@inheritDoc}
332 * @throws NullPointerException if the specified element is null
333 */
334 public E ceiling(E e) {
335 return m.ceilingKey(e);
336 }
337
338 /**
339 * @throws ClassCastException {@inheritDoc}
340 * @throws NullPointerException if the specified element is null
341 */
342 public E higher(E e) {
343 return m.higherKey(e);
344 }
345
346 public E pollFirst() {
347 Map.Entry<E,Object> e = m.pollFirstEntry();
348 return (e == null) ? null : e.getKey();
349 }
350
351 public E pollLast() {
352 Map.Entry<E,Object> e = m.pollLastEntry();
353 return (e == null) ? null : e.getKey();
354 }
355
356
357 /* ---------------- SortedSet operations -------------- */
358
359
360 public Comparator<? super E> comparator() {
361 return m.comparator();
362 }
363
364 /**
365 * @throws java.util.NoSuchElementException {@inheritDoc}
366 */
367 public E first() {
368 return m.firstKey();
369 }
370
371 /**
372 * @throws java.util.NoSuchElementException {@inheritDoc}
373 */
374 public E last() {
375 return m.lastKey();
376 }
377
378 /**
379 * @throws ClassCastException {@inheritDoc}
380 * @throws NullPointerException if {@code fromElement} or
381 * {@code toElement} is null
382 * @throws IllegalArgumentException {@inheritDoc}
383 */
384 public NavigableSet<E> subSet(E fromElement,
385 boolean fromInclusive,
386 E toElement,
387 boolean toInclusive) {
388 return new ConcurrentSkipListSet<E>
389 (m.subMap(fromElement, fromInclusive,
390 toElement, toInclusive));
391 }
392
393 /**
394 * @throws ClassCastException {@inheritDoc}
395 * @throws NullPointerException if {@code toElement} is null
396 * @throws IllegalArgumentException {@inheritDoc}
397 */
398 public NavigableSet<E> headSet(E toElement, boolean inclusive) {
399 return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));
400 }
401
402 /**
403 * @throws ClassCastException {@inheritDoc}
404 * @throws NullPointerException if {@code fromElement} is null
405 * @throws IllegalArgumentException {@inheritDoc}
406 */
407 public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
408 return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive));
409 }
410
411 /**
412 * @throws ClassCastException {@inheritDoc}
413 * @throws NullPointerException if {@code fromElement} or
414 * {@code toElement} is null
415 * @throws IllegalArgumentException {@inheritDoc}
416 */
417 public NavigableSet<E> subSet(E fromElement, E toElement) {
418 return subSet(fromElement, true, toElement, false);
419 }
420
421 /**
422 * @throws ClassCastException {@inheritDoc}
423 * @throws NullPointerException if {@code toElement} is null
424 * @throws IllegalArgumentException {@inheritDoc}
425 */
426 public NavigableSet<E> headSet(E toElement) {
427 return headSet(toElement, false);
428 }
429
430 /**
431 * @throws ClassCastException {@inheritDoc}
432 * @throws NullPointerException if {@code fromElement} is null
433 * @throws IllegalArgumentException {@inheritDoc}
434 */
435 public NavigableSet<E> tailSet(E fromElement) {
436 return tailSet(fromElement, true);
437 }
438
439 /**
440 * Returns a reverse order view of the elements contained in this set.
441 * The descending set is backed by this set, so changes to the set are
442 * reflected in the descending set, and vice-versa.
443 *
444 * <p>The returned set has an ordering equivalent to
445 * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
446 * The expression {@code s.descendingSet().descendingSet()} returns a
447 * view of {@code s} essentially equivalent to {@code s}.
448 *
449 * @return a reverse order view of this set
450 */
451 public NavigableSet<E> descendingSet() {
452 return new ConcurrentSkipListSet<E>(m.descendingMap());
453 }
454
455 /**
456 * Returns a {@link Spliterator} over the elements in this set.
457 *
458 * <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
459 * {@link Spliterator#NONNULL}, {@link Spliterator#DISTINCT},
460 * {@link Spliterator#SORTED}, and {@link Spliterator#ORDERED} with an
461 * encounter order that is ascending order. Overriding implementations
462 * should document the reporting of additional characteristic values.
463 *
464 * <p>The spliterator's comparator (see
465 * {@link java.util.Spliterator#getComparator()}) is {@code null} if
466 * the set's comparator (see {@link #comparator()}) is {@code null}.
467 * Otherwise, the spliterator's comparator is the same as or imposes the
468 * same total ordering as the set's comparator.
469 *
470 * @return a {@code Spliterator} over the elements in this set
471 * @since 1.8
472 */
473 @SuppressWarnings("unchecked")
474 public Spliterator<E> spliterator() {
475 if (m instanceof ConcurrentSkipListMap)
476 return ((ConcurrentSkipListMap<E,?>)m).keySpliterator();
477 else
478 return (Spliterator<E>)((ConcurrentSkipListMap.SubMap<E,?>)m).keyIterator();
479 }
480
481 // Support for resetting map in clone
482 private void setMap(ConcurrentNavigableMap<E,Object> map) {
483 UNSAFE.putObjectVolatile(this, mapOffset, map);
484 }
485
486 private static final sun.misc.Unsafe UNSAFE;
487 private static final long mapOffset;
488 static {
489 try {
490 UNSAFE = sun.misc.Unsafe.getUnsafe();
491 Class<?> k = ConcurrentSkipListSet.class;
492 mapOffset = UNSAFE.objectFieldOffset
493 (k.getDeclaredField("m"));
494 } catch (Exception e) {
495 throw new Error(e);
496 }
497 }
498 }