ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk7/java/util/concurrent/ConcurrentSkipListSet.java
Revision: 1.2
Committed: Wed Jan 16 01:39:37 2013 UTC (11 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.1: +32 -32 lines
Log Message:
<tt> -> {@code

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