ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166x/ConcurrentSkipListSet.java
Revision: 1.1
Committed: Wed Aug 11 10:58:15 2004 UTC (19 years, 8 months ago) by dl
Branch: MAIN
Log Message:
Initial checkin of initial jsr166x package and skip list classes

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 SortedSet} and (priority) {@link
14 * Queue} implementation based on a {@link ConcurrentSkipListMap}.
15 * This class maintains a set in ascending order, sorted according to
16 * the <i>natural order</i> for the element's class (see {@link
17 * Comparable}), or by the comparator provided at creation time,
18 * depending on which constructor is 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 procede concurrently with
28 * other operations.
29 *
30 * <p>This class provides extended <tt>SortedSet</tt> methods
31 * searching for closest matches. Methods <tt>lower</tt>,
32 * <tt>floor</tt>, <tt>ceiling</tt>, and <tt>higher</tt> return
33 * elements respectively less, less than or equal, greater than or
34 * equal, and greater than a given value, returning null if there is
35 * no such element. These methods are designed for locating, not
36 * traversing entries. To traverse, use iterators and/or
37 * <tt>subset</tt>.
38 *
39 * <p>The class additionally supports {@link Queue} methods such as
40 * <tt>poll</tt> that atomically returns and removes the first
41 * element, if one exists. Thus, this class can serve as a priority
42 * queue in which there are no duplicate elements.
43 *
44 * <p>The {@link ConcurrentSkipListSubSet} objects returned by methods
45 * <tt>subset</tt>, <tt>headSet</tt>, and <tt>tailSet</tt> support the
46 * same extended set of operations as this class, but operate on their
47 * designated subrange of elements.
48 *
49 * <p>Beware that, unlike in most collections, the <tt>size</tt>
50 * method is <em>NOT</em> a constant-time operation. Because of the
51 * asynchronous nature of these sets, determining the current number
52 * of elements requires a traversal of the elements.
53 *
54 * <p>This class and its iterators implement all of the
55 * <em>optional</em> methods of the {@link Set} and {@link Iterator}
56 * interfaces. Like most other concurrent collection implementations,
57 * this class does not permit the use of <tt>null</tt> elements.
58 * because null arguments and return values cannot be reliably
59 * distinguished from the absence of elements.
60 *
61 * @author Doug Lea
62 * @param <E> the type of elements maintained by this set
63 */
64 public class ConcurrentSkipListSet<E>
65 extends AbstractSet<E>
66 implements SortedSet<E>, Queue<E>, Cloneable, java.io.Serializable {
67
68 private static final long serialVersionUID = -2479143111061671589L;
69
70 /**
71 * The underlying map. Uses Boolean.TRUE as value for each
72 * element. Note that this class relies on default serialization,
73 * which is a little wasteful in saving all of the useless value
74 * fields of underlying map, but enables this field to be declared
75 * final, which is necessary for thread safety.
76 */
77 private final ConcurrentSkipListMap<E,Object> m;
78
79 /**
80 * Constructs a new, empty set, sorted according to the elements' natural
81 * order.
82 */
83 public ConcurrentSkipListSet() {
84 m = new ConcurrentSkipListMap<E,Object>();
85 }
86
87 /**
88 * Constructs a new, empty set, sorted according to the specified
89 * comparator.
90 *
91 * @param c the comparator that will be used to sort this set. A
92 * <tt>null</tt> value indicates that the elements' <i>natural
93 * ordering</i> should be used.
94 */
95 public ConcurrentSkipListSet(Comparator<? super E> c) {
96 m = new ConcurrentSkipListMap<E,Object>(c);
97 }
98
99 /**
100 * Constructs a new set containing the elements in the specified
101 * collection, sorted according to the elements' <i>natural order</i>.
102 *
103 * @param c The elements that will comprise the new set.
104 *
105 * @throws ClassCastException if the elements in the specified
106 * collection are not comparable, or are not mutually comparable.
107 * @throws NullPointerException if the specified collection is 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 as the specified
116 * sorted set, sorted according to the same ordering.
117 *
118 * @param s sorted set whose elements will comprise the new set.
119 * @throws NullPointerException if the specified sorted set is null.
120 */
121 public ConcurrentSkipListSet(SortedSet<E> s) {
122 m = new ConcurrentSkipListMap<E,Object>(s.comparator());
123 addAll(s);
124 }
125
126 /**
127 * Returns a shallow copy of this set. (The elements themselves
128 * are not cloned.)
129 *
130 * @return a shallow copy of this set.
131 */
132 public Object clone() {
133 ConcurrentSkipListSet<E> clone = null;
134 try {
135 clone = (ConcurrentSkipListSet<E>) super.clone();
136 } catch (CloneNotSupportedException e) {
137 throw new InternalError();
138 }
139
140 clone.m.initialize();
141 clone.addAll(this);
142 return clone;
143 }
144
145 /* ---------------- Set operations -------------- */
146
147 /**
148 * Returns the number of elements in this set. If this set
149 * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
150 * returns <tt>Integer.MAX_VALUE</tt>.
151 *
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 * @return the number of elements in this set.
162 */
163 public int size() {
164 return m.size();
165 }
166
167 /**
168 * Returns <tt>true</tt> if this set contains no elements.
169 * @return <tt>true</tt> if this set contains no elements.
170 */
171 public boolean isEmpty() {
172 return m.isEmpty();
173 }
174
175 /**
176 * Returns <tt>true</tt> if this set contains the specified element.
177 *
178 * @param o the object to be checked for containment in this set.
179 * @return <tt>true</tt> if this set contains the specified element.
180 *
181 * @throws ClassCastException if the specified object cannot be compared
182 * with the elements currently in the set.
183 * @throws NullPointerException if o is <tt>null</tt>.
184 */
185 public boolean contains(Object o) {
186 return m.containsKey(o);
187 }
188
189 /**
190 * Adds the specified element to this set if it is not already present.
191 *
192 * @param o element to be added to this set.
193 * @return <tt>true</tt> if the set did not already contain the specified
194 * element.
195 *
196 * @throws ClassCastException if the specified object cannot be compared
197 * with the elements currently in the set.
198 * @throws NullPointerException if o is <tt>null</tt>.
199 */
200 public boolean add(E o) {
201 return m.putIfAbsent(o, Boolean.TRUE) == null;
202 }
203
204 /**
205 * Removes the specified element from this set if it is present.
206 *
207 * @param o object to be removed from this set, if present.
208 * @return <tt>true</tt> if the set contained the specified element.
209 *
210 * @throws ClassCastException if the specified object cannot be compared
211 * with the elements currently in the set.
212 * @throws NullPointerException if o is <tt>null</tt>.
213 */
214 public boolean remove(Object o) {
215 return m.removep(o);
216 }
217
218 /**
219 * Removes all of the elements from this set.
220 */
221 public void clear() {
222 m.clear();
223 }
224
225 /**
226 * Returns an iterator over the elements in this set. The elements
227 * are returned in ascending order.
228 *
229 * @return an iterator over the elements in this set.
230 */
231 public Iterator<E> iterator() {
232 return m.keyIterator();
233 }
234
235 /* ---------------- Queue operations -------------- */
236
237 /**
238 * Adds the specified element, or fails if this element is already
239 * present.
240 * @param o the element to insert.
241 * @return <tt>true</tt> if it was possible to add the element,
242 * else <tt>false</tt>
243 */
244 public boolean offer(E o) {
245 return add(o);
246 }
247
248 /**
249 * Retrieves and removes the first (lowest) element.
250 *
251 * @return the least element, or <tt>null</tt> if empty.
252 */
253 public E poll() {
254 return m.removeFirstKey();
255 }
256
257 /**
258 * Retrieves and removes the first (lowest) element. This method
259 * differs from the <tt>poll</tt> method in that it throws an
260 * exception if empty.
261 *
262 * @return the first (lowest) element.
263 * @throws NoSuchElementException if empty.
264 */
265 public E remove() {
266 E x = m.removeFirstKey();
267 if (x == null)
268 throw new NoSuchElementException();
269 return x;
270 }
271
272 /**
273 * Retrieves, but does not remove, the first (lowest) element,
274 * returning <tt>null</tt> if empty.
275 *
276 * @return the first (lowest) element, or <tt>null</tt> if empty.
277 */
278 public E peek() {
279 return m.lowestKey();
280 }
281
282 /**
283 * Retrieves, but does not remove, the first (lowest) element.
284 * This method differs from the <tt>peek</tt> method only in that
285 * it throws an exception if empty.
286 *
287 * @return the first (lowest) element.
288 * @throws NoSuchElementException if empty.
289 */
290 public E element() {
291 return m.firstKey();
292 }
293
294 /* ---------------- Relational operations -------------- */
295
296 /**
297 * Returns an element greater than or equal to the given element, or
298 * null if there is no such element.
299 *
300 * @param o the value to match
301 * @return an element greater than or equal to given element, or null
302 * if there is no such element.
303 * @throws ClassCastException if o cannot be compared with the elements
304 * currently in the set.
305 * @throws NullPointerException if o is <tt>null</tt>
306 */
307 public E ceiling(E o) {
308 return m.ceilingKey(o);
309 }
310
311 /**
312 * Returns an element strictly less than the given element, or null if
313 * there is no such element.
314 *
315 * @param o the value to match
316 * @return the greatest element less than the given element, or
317 * null if there is no such element.
318 * @throws ClassCastException if o cannot be compared with the elements
319 * currently in the set.
320 * @throws NullPointerException if o is <tt>null</tt>.
321 */
322 public E lower(E o) {
323 return m.lowerKey(o);
324 }
325
326 /**
327 * Returns an element less than or equal to the given element, or null
328 * if there is no such element.
329 *
330 * @param o the value to match
331 * @return the greatest element less than or equal to given
332 * element, or null if there is no such element.
333 * @throws ClassCastException if o cannot be compared with the elements
334 * currently in the set.
335 * @throws NullPointerException if o is <tt>null</tt>.
336 */
337 public E floor(E o) {
338 return m.floorKey(o);
339 }
340
341 /**
342 * Returns an element strictly greater than the given element, or null
343 * if there is no such element.
344 *
345 * @param o the value to match
346 * @return the least element greater than the given element, or
347 * null if there is no such element.
348 * @throws ClassCastException if o cannot be compared with the elements
349 * currently in the set.
350 * @throws NullPointerException if o is <tt>null</tt>.
351 */
352 public E higher(E o) {
353 return m.higherKey(o);
354 }
355
356 /* ---------------- SortedSet operations -------------- */
357
358
359 /**
360 * Returns the comparator used to order this set, or <tt>null</tt>
361 * if this set uses its elements natural ordering.
362 *
363 * @return the comparator used to order this set, or <tt>null</tt>
364 * if this set uses its elements natural ordering.
365 */
366 public Comparator<? super E> comparator() {
367 return m.comparator();
368 }
369
370 /**
371 * Returns the first (lowest) element currently in this set.
372 *
373 * @return the first (lowest) element currently in this set.
374 * @throws NoSuchElementException sorted set is empty.
375 */
376 public E first() {
377 return m.firstKey();
378 }
379
380 /**
381 * Returns the last (highest) element currently in this set.
382 *
383 * @return the last (highest) element currently in this set.
384 * @throws NoSuchElementException sorted set is empty.
385 */
386 public E last() {
387 return m.lastKey();
388 }
389
390 /**
391 * Returns a view of the portion of this set whose elements range from
392 * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive. (If
393 * <tt>fromElement</tt> and <tt>toElement</tt> are equal, the returned
394 * sorted set is empty.) The returned sorted set is backed by this set,
395 * so changes in the returned sorted set are reflected in this set, and
396 * vice-versa.
397 * @param fromElement low endpoint (inclusive) of the subSet.
398 * @param toElement high endpoint (exclusive) of the subSet.
399 * @return a view of the portion of this set whose elements range from
400 * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
401 * exclusive.
402 * @throws ClassCastException if <tt>fromElement</tt> and
403 * <tt>toElement</tt> cannot be compared to one another using
404 * this set's comparator (or, if the set has no comparator,
405 * using natural ordering).
406 * @throws IllegalArgumentException if <tt>fromElement</tt> is
407 * greater than <tt>toElement</tt>.
408 * @throws NullPointerException if <tt>fromElement</tt> or
409 * <tt>toElement</tt> is <tt>null</tt>.
410 */
411 public ConcurrentSkipListSubSet<E> subSet(E fromElement, E toElement) {
412 return new ConcurrentSkipListSubSet<E>(m, fromElement, toElement);
413 }
414
415 /**
416 * Returns a view of the portion of this set whose elements are strictly
417 * less than <tt>toElement</tt>. The returned sorted set is backed by
418 * this set, so changes in the returned sorted set are reflected in this
419 * set, and vice-versa.
420 * @param toElement high endpoint (exclusive) of the headSet.
421 * @return a view of the portion of this set whose elements are strictly
422 * less than toElement.
423 * @throws ClassCastException if <tt>toElement</tt> is not compatible
424 * with this set's comparator (or, if the set has no comparator,
425 * if <tt>toElement</tt> does not implement <tt>Comparable</tt>).
426 * @throws NullPointerException if <tt>toElement</tt> is <tt>null</tt>.
427 */
428 public ConcurrentSkipListSubSet<E> headSet(E toElement) {
429 return new ConcurrentSkipListSubSet<E>(m, null, toElement);
430 }
431
432
433 /**
434 * Returns a view of the portion of this set whose elements are
435 * greater than or equal to <tt>fromElement</tt>. The returned
436 * sorted set is backed by this set, so changes in the returned
437 * sorted set are reflected in this set, and vice-versa.
438 * @param fromElement low endpoint (inclusive) of the tailSet.
439 * @return a view of the portion of this set whose elements are
440 * greater than or equal to <tt>fromElement</tt>.
441 * @throws ClassCastException if <tt>fromElement</tt> is not
442 * compatible with this set's comparator (or, if the set has no
443 * comparator, if <tt>fromElement</tt> does not implement
444 * <tt>Comparable</tt>).
445 * @throws NullPointerException if <tt>fromElement</tt> is <tt>null</tt>.
446 */
447 public ConcurrentSkipListSubSet<E> tailSet(E fromElement) {
448 return new ConcurrentSkipListSubSet<E>(m, fromElement, null);
449 }
450 }