ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentSkipListSet.java
Revision: 1.31
Committed: Wed Jan 16 15:04:03 2013 UTC (11 years, 4 months ago) by dl
Branch: MAIN
Changes since 1.30: +29 -0 lines
Log Message:
lambda-lib support

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