ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/ConcurrentSkipListSet.java
Revision: 1.2
Committed: Sat Mar 11 17:36:10 2017 UTC (7 years, 2 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -1 lines
Log Message:
fix unused imports reported by errorprone [RemoveUnusedImports]

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