ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166x/ConcurrentSkipListSet.java
Revision: 1.4
Committed: Sat Oct 16 14:49:45 2004 UTC (19 years, 6 months ago) by dl
Branch: MAIN
Changes since 1.3: +75 -14 lines
Log Message:
Improve pollLast* implementation; other minor touchups

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/licenses/publicdomain
5     */
6    
7     package jsr166x;
8    
9     import java.util.*;
10     import java.util.concurrent.*;
11    
12     /**
13 dl 1.2 * A scalable concurrent {@link NavigableSet} implementation based on
14     * a {@link ConcurrentSkipListMap}. This class maintains a set in
15     * ascending order, sorted according to the <i>natural order</i> for
16     * the element's class (see {@link Comparable}), or by the comparator
17     * provided at creation time, depending on which constructor is
18     * used.<p>
19 dl 1.1 *
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>Beware that, unlike in most collections, the <tt>size</tt>
31 dl 1.4 * method is <em>not</em> a constant-time operation. Because of the
32 dl 1.1 * asynchronous nature of these sets, determining the current number
33 dl 1.4 * of elements requires a traversal of the elements. Additionally, the
34     * bulk operations <tt>addAll</tt>, <tt>removeAll</tt>,
35     * <<tt>retainAll</tt>, and tt>containsAll</tt> are <em>not</em>
36     * guaranteed to be performed atomically. For example, an iterator
37     * operating concurrently with an <tt>addAll</tt> operation might view
38     * only some of the added elements.
39 dl 1.1 *
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     * this class does not permit the use of <tt>null</tt> elements.
44 dl 1.3 * because <tt>null</tt> arguments and return values cannot be reliably
45 dl 1.1 * distinguished from the absence of elements.
46     *
47     * @author Doug Lea
48     * @param <E> the type of elements maintained by this set
49     */
50     public class ConcurrentSkipListSet<E>
51     extends AbstractSet<E>
52 dl 1.2 implements NavigableSet<E>, Cloneable, java.io.Serializable {
53 dl 1.1
54     private static final long serialVersionUID = -2479143111061671589L;
55    
56     /**
57     * The underlying map. Uses Boolean.TRUE as value for each
58     * element. Note that this class relies on default serialization,
59     * which is a little wasteful in saving all of the useless value
60     * fields of underlying map, but enables this field to be declared
61     * final, which is necessary for thread safety.
62     */
63     private final ConcurrentSkipListMap<E,Object> m;
64    
65     /**
66     * Constructs a new, empty set, sorted according to the elements' natural
67     * order.
68     */
69     public ConcurrentSkipListSet() {
70     m = new ConcurrentSkipListMap<E,Object>();
71     }
72    
73     /**
74     * Constructs a new, empty set, sorted according to the specified
75     * comparator.
76     *
77     * @param c the comparator that will be used to sort this set. A
78     * <tt>null</tt> value indicates that the elements' <i>natural
79     * ordering</i> should be used.
80     */
81     public ConcurrentSkipListSet(Comparator<? super E> c) {
82     m = new ConcurrentSkipListMap<E,Object>(c);
83     }
84    
85     /**
86     * Constructs a new set containing the elements in the specified
87     * collection, sorted according to the elements' <i>natural order</i>.
88     *
89     * @param c The elements that will comprise the new set.
90     *
91     * @throws ClassCastException if the elements in the specified
92     * collection are not comparable, or are not mutually comparable.
93 dl 1.4 * @throws NullPointerException if the specified collection is
94     * <tt>null</tt>.
95 dl 1.1 */
96     public ConcurrentSkipListSet(Collection<? extends E> c) {
97     m = new ConcurrentSkipListMap<E,Object>();
98     addAll(c);
99     }
100    
101     /**
102     * Constructs a new set containing the same elements as the specified
103     * sorted set, sorted according to the same ordering.
104     *
105     * @param s sorted set whose elements will comprise the new set.
106 dl 1.4 * @throws NullPointerException if the specified sorted set is
107     * <tt>null</tt>.
108 dl 1.1 */
109     public ConcurrentSkipListSet(SortedSet<E> s) {
110     m = new ConcurrentSkipListMap<E,Object>(s.comparator());
111     addAll(s);
112     }
113    
114     /**
115     * Returns a shallow copy of this set. (The elements themselves
116     * are not cloned.)
117     *
118     * @return a shallow copy of this set.
119     */
120     public Object clone() {
121     ConcurrentSkipListSet<E> clone = null;
122     try {
123     clone = (ConcurrentSkipListSet<E>) super.clone();
124     } catch (CloneNotSupportedException e) {
125     throw new InternalError();
126     }
127    
128     clone.m.initialize();
129     clone.addAll(this);
130     return clone;
131     }
132    
133     /* ---------------- Set operations -------------- */
134    
135     /**
136     * Returns the number of elements in this set. If this set
137     * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
138     * returns <tt>Integer.MAX_VALUE</tt>.
139     *
140     * <p>Beware that, unlike in most collections, this method is
141     * <em>NOT</em> a constant-time operation. Because of the
142     * asynchronous nature of these sets, determining the current
143     * number of elements requires traversing them all to count them.
144     * Additionally, it is possible for the size to change during
145     * execution of this method, in which case the returned result
146     * will be inaccurate. Thus, this method is typically not very
147     * useful in concurrent applications.
148     *
149     * @return the number of elements in this set.
150     */
151     public int size() {
152     return m.size();
153     }
154    
155     /**
156     * Returns <tt>true</tt> if this set contains no elements.
157     * @return <tt>true</tt> if this set contains no elements.
158     */
159     public boolean isEmpty() {
160     return m.isEmpty();
161     }
162    
163     /**
164     * Returns <tt>true</tt> if this set contains the specified element.
165     *
166     * @param o the object to be checked for containment in this set.
167     * @return <tt>true</tt> if this set contains the specified element.
168     *
169     * @throws ClassCastException if the specified object cannot be compared
170     * with the elements currently in the set.
171     * @throws NullPointerException if o is <tt>null</tt>.
172     */
173     public boolean contains(Object o) {
174     return m.containsKey(o);
175     }
176    
177     /**
178     * Adds the specified element to this set if it is not already present.
179     *
180     * @param o element to be added to this set.
181     * @return <tt>true</tt> if the set did not already contain the specified
182     * element.
183     *
184     * @throws ClassCastException if the specified object cannot be compared
185     * with the elements currently in the set.
186     * @throws NullPointerException if o is <tt>null</tt>.
187     */
188     public boolean add(E o) {
189     return m.putIfAbsent(o, Boolean.TRUE) == null;
190     }
191    
192     /**
193     * Removes the specified element from this set if it is present.
194     *
195     * @param o object to be removed from this set, if present.
196     * @return <tt>true</tt> if the set contained the specified element.
197     *
198     * @throws ClassCastException if the specified object cannot be compared
199     * with the elements currently in the set.
200     * @throws NullPointerException if o is <tt>null</tt>.
201     */
202     public boolean remove(Object o) {
203     return m.removep(o);
204     }
205    
206     /**
207     * Removes all of the elements from this set.
208     */
209     public void clear() {
210     m.clear();
211     }
212    
213     /**
214     * Returns an iterator over the elements in this set. The elements
215     * are returned in ascending order.
216     *
217     * @return an iterator over the elements in this set.
218     */
219     public Iterator<E> iterator() {
220     return m.keyIterator();
221     }
222 dl 1.4
223     /* ---------------- AbstractSet Overrides -------------- */
224    
225     /**
226     * Compares the specified object with this set for equality. Returns
227     * <tt>true</tt> if the specified object is also a set, the two sets
228     * have the same size, and every member of the specified set is
229     * contained in this set (or equivalently, every member of this set is
230     * contained in the specified set). This definition ensures that the
231     * equals method works properly across different implementations of the
232     * set interface.
233     *
234     * @param o Object to be compared for equality with this set.
235     * @return <tt>true</tt> if the specified Object is equal to this set.
236     */
237     public boolean equals(Object o) {
238     // Override AbstractSet version to avoid calling size()
239     if (o == this)
240     return true;
241     if (!(o instanceof Set))
242     return false;
243     Collection c = (Collection) o;
244     try {
245     return containsAll(c) && c.containsAll(this);
246     } catch(ClassCastException unused) {
247     return false;
248     } catch(NullPointerException unused) {
249     return false;
250     }
251     }
252    
253     /**
254     * Removes from this set all of its elements that are contained in
255     * the specified collection. If the specified collection is also
256     * a set, this operation effectively modifies this set so that its
257     * value is the <i>asymmetric set difference</i> of the two sets.
258     *
259     * @param c collection that defines which elements will be removed from
260     * this set.
261     * @return <tt>true</tt> if this set changed as a result of the call.
262     *
263     * @throws ClassCastException if the types of one or more elements in this
264     * set are incompatible with the specified collection
265     * @throws NullPointerException if the specified collection, or any
266     * of its elements are <tt>null</tt>.
267     */
268     public boolean removeAll(Collection<?> c) {
269     // Override AbstractSet version to avoid unnecessary call to size()
270     boolean modified = false;
271     for (Iterator<?> i = c.iterator(); i.hasNext(); )
272     if (remove(i.next()))
273     modified = true;
274     return modified;
275     }
276 dl 1.1
277     /* ---------------- Relational operations -------------- */
278    
279     /**
280     * Returns an element greater than or equal to the given element, or
281 dl 1.3 * <tt>null</tt> if there is no such element.
282 dl 1.1 *
283     * @param o the value to match
284 dl 1.4 * @return an element greater than or equal to given element, or
285     * <tt>null</tt> if there is no such element.
286 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
287     * currently in the set.
288     * @throws NullPointerException if o is <tt>null</tt>
289     */
290     public E ceiling(E o) {
291     return m.ceilingKey(o);
292     }
293    
294     /**
295 dl 1.4 * Returns an element strictly less than the given element, or
296     * <tt>null</tt> if there is no such element.
297 dl 1.1 *
298     * @param o the value to match
299     * @return the greatest element less than the given element, or
300 dl 1.3 * <tt>null</tt> if there is no such element.
301 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
302     * currently in the set.
303     * @throws NullPointerException if o is <tt>null</tt>.
304     */
305     public E lower(E o) {
306     return m.lowerKey(o);
307     }
308    
309     /**
310 dl 1.4 * Returns an element less than or equal to the given element, or
311     * <tt>null</tt> if there is no such element.
312 dl 1.1 *
313     * @param o the value to match
314     * @return the greatest element less than or equal to given
315 dl 1.3 * element, or <tt>null</tt> if there is no such element.
316 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
317     * currently in the set.
318     * @throws NullPointerException if o is <tt>null</tt>.
319     */
320     public E floor(E o) {
321     return m.floorKey(o);
322     }
323    
324     /**
325 dl 1.4 * Returns an element strictly greater than the given element, or
326     * <tt>null</tt> if there is no such element.
327 dl 1.1 *
328     * @param o the value to match
329     * @return the least element greater than the given element, or
330 dl 1.3 * <tt>null</tt> if there is no such element.
331 dl 1.1 * @throws ClassCastException if o cannot be compared with the elements
332     * currently in the set.
333     * @throws NullPointerException if o is <tt>null</tt>.
334     */
335     public E higher(E o) {
336     return m.higherKey(o);
337     }
338    
339 dl 1.2 /**
340     * Retrieves and removes the first (lowest) element.
341     *
342     * @return the least element, or <tt>null</tt> if empty.
343     */
344     public E pollFirst() {
345     return m.removeFirstKey();
346     }
347    
348     /**
349     * Retrieves and removes the last (highest) element.
350     *
351     * @return the last element, or <tt>null</tt> if empty.
352     */
353     public E pollLast() {
354     return m.removeLastKey();
355     }
356    
357    
358 dl 1.1 /* ---------------- SortedSet operations -------------- */
359    
360    
361     /**
362     * Returns the comparator used to order this set, or <tt>null</tt>
363     * if this set uses its elements natural ordering.
364     *
365     * @return the comparator used to order this set, or <tt>null</tt>
366     * if this set uses its elements natural ordering.
367     */
368     public Comparator<? super E> comparator() {
369     return m.comparator();
370     }
371    
372     /**
373     * Returns the first (lowest) element currently in this set.
374     *
375     * @return the first (lowest) element currently in this set.
376     * @throws NoSuchElementException sorted set is empty.
377     */
378     public E first() {
379     return m.firstKey();
380     }
381    
382     /**
383     * Returns the last (highest) element currently in this set.
384     *
385     * @return the last (highest) element currently in this set.
386     * @throws NoSuchElementException sorted set is empty.
387     */
388     public E last() {
389     return m.lastKey();
390     }
391    
392 dl 1.4
393    
394 dl 1.1 /**
395     * Returns a view of the portion of this set whose elements range from
396     * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive. (If
397     * <tt>fromElement</tt> and <tt>toElement</tt> are equal, the returned
398     * sorted set is empty.) The returned sorted set is backed by this set,
399     * so changes in the returned sorted set are reflected in this set, and
400     * vice-versa.
401     * @param fromElement low endpoint (inclusive) of the subSet.
402     * @param toElement high endpoint (exclusive) of the subSet.
403     * @return a view of the portion of this set whose elements range from
404     * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
405     * exclusive.
406     * @throws ClassCastException if <tt>fromElement</tt> and
407     * <tt>toElement</tt> cannot be compared to one another using
408     * this set's comparator (or, if the set has no comparator,
409     * using natural ordering).
410     * @throws IllegalArgumentException if <tt>fromElement</tt> is
411     * greater than <tt>toElement</tt>.
412     * @throws NullPointerException if <tt>fromElement</tt> or
413     * <tt>toElement</tt> is <tt>null</tt>.
414     */
415 dl 1.2 public NavigableSet<E> subSet(E fromElement, E toElement) {
416 dl 1.1 return new ConcurrentSkipListSubSet<E>(m, fromElement, toElement);
417     }
418    
419     /**
420     * Returns a view of the portion of this set whose elements are strictly
421     * less than <tt>toElement</tt>. The returned sorted set is backed by
422     * this set, so changes in the returned sorted set are reflected in this
423     * set, and vice-versa.
424     * @param toElement high endpoint (exclusive) of the headSet.
425     * @return a view of the portion of this set whose elements are strictly
426     * less than toElement.
427     * @throws ClassCastException if <tt>toElement</tt> is not compatible
428     * with this set's comparator (or, if the set has no comparator,
429     * if <tt>toElement</tt> does not implement <tt>Comparable</tt>).
430     * @throws NullPointerException if <tt>toElement</tt> is <tt>null</tt>.
431     */
432 dl 1.2 public NavigableSet<E> headSet(E toElement) {
433 dl 1.1 return new ConcurrentSkipListSubSet<E>(m, null, toElement);
434     }
435    
436    
437     /**
438     * Returns a view of the portion of this set whose elements are
439     * greater than or equal to <tt>fromElement</tt>. The returned
440     * sorted set is backed by this set, so changes in the returned
441     * sorted set are reflected in this set, and vice-versa.
442     * @param fromElement low endpoint (inclusive) of the tailSet.
443     * @return a view of the portion of this set whose elements are
444     * greater than or equal to <tt>fromElement</tt>.
445     * @throws ClassCastException if <tt>fromElement</tt> is not
446     * compatible with this set's comparator (or, if the set has no
447     * comparator, if <tt>fromElement</tt> does not implement
448     * <tt>Comparable</tt>).
449     * @throws NullPointerException if <tt>fromElement</tt> is <tt>null</tt>.
450     */
451 dl 1.2 public NavigableSet<E> tailSet(E fromElement) {
452 dl 1.1 return new ConcurrentSkipListSubSet<E>(m, fromElement, null);
453     }
454 dl 1.2
455     /**
456     * Subsets returned by {@link ConcurrentSkipListSet} subset operations
457     * represent a subrange of elements of their underlying
458     * sets. Instances of this class support all methods of their
459     * underlying sets, differing in that elements outside their range are
460     * ignored, and attempts to add elements outside their ranges result
461     * in {@link IllegalArgumentException}. Instances of this class are
462     * constructed only using the <tt>subSet</tt>, <tt>headSet</tt>, and
463     * <tt>tailSet</tt> methods of their underlying sets.
464     *
465     */
466     static class ConcurrentSkipListSubSet<E>
467     extends AbstractSet<E>
468     implements NavigableSet<E>, java.io.Serializable {
469    
470     private static final long serialVersionUID = -7647078645896651609L;
471    
472     /** The underlying submap */
473     private final ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object> s;
474    
475     /**
476     * Creates a new submap.
477 dl 1.3 * @param fromElement inclusive least value, or <tt>null</tt> if from start
478     * @param toElement exclusive upper bound or <tt>null</tt> if to end
479 dl 1.2 * @throws IllegalArgumentException if fromElement and toElement
480     * nonnull and fromElement greater than toElement
481     */
482     ConcurrentSkipListSubSet(ConcurrentSkipListMap<E,Object> map,
483     E fromElement, E toElement) {
484     s = new ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object>(map, fromElement,
485     toElement);
486     }
487    
488     /**
489     * Returns the number of elements in this set. If this set
490     * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
491     * returns <tt>Integer.MAX_VALUE</tt>.
492     *
493     * <p>Beware that, unlike in most collections, this method is
494     * <em>NOT</em> a constant-time operation. Because of the
495     * asynchronous nature of these sets, determining the current
496     * number of elements requires traversing them all to count them.
497     * Additionally, it is possible for the size to change during
498     * execution of this method, in which case the returned result
499     * will be inaccurate. Thus, this method is typically not very
500     * useful in concurrent applications.
501     *
502     * @return the number of elements in this set.
503     */
504     public int size() {
505     return s.size();
506     }
507    
508     /**
509     * Returns <tt>true</tt> if this set contains no elements.
510     * @return <tt>true</tt> if this set contains no elements.
511     */
512     public boolean isEmpty() {
513     return s.isEmpty();
514     }
515    
516     /**
517     * Returns <tt>true</tt> if this set contains the specified
518     * element.
519     *
520     * @param o the object to be checked for containment in this
521     * set.
522     * @return <tt>true</tt> if this set contains the specified
523     * element.
524     *
525     * @throws ClassCastException if the specified object cannot
526     * be compared with the elements currently in the set.
527     * @throws NullPointerException if o is <tt>null</tt>.
528     */
529     public boolean contains(Object o) {
530     return s.containsKey(o);
531     }
532    
533    
534     /**
535     * Adds the specified element to this set if it is not already
536     * present.
537     *
538     * @param o element to be added to this set.
539     * @return <tt>true</tt> if the set did not already contain
540     * the specified element.
541     *
542     * @throws ClassCastException if the specified object cannot
543     * be compared with the elements currently in the set.
544     * @throws IllegalArgumentException if o is outside the range
545     * of this subset.
546     * @throws NullPointerException if o is <tt>null</tt>.
547     */
548     public boolean add(E o) {
549     return s.put(o, Boolean.TRUE) == null;
550     }
551    
552     /**
553     * Removes the specified element from this set if it is
554     * present.
555     *
556     * @param o object to be removed from this set, if present.
557     * @return <tt>true</tt> if the set contained the specified element.
558     *
559     * @throws ClassCastException if the specified object cannot
560     * be compared with the elements currently in the set.
561     * @throws NullPointerException if o is <tt>null</tt>.
562     */
563     public boolean remove(Object o) {
564     return s.remove(o) != null;
565     }
566    
567     /**
568     * Removes all of the elements from this set.
569     */
570     public void clear() {
571     s.clear();
572     }
573    
574     /**
575     * Returns an iterator over the elements in this set. The elements
576     * are returned in ascending order.
577     *
578     * @return an iterator over the elements in this set.
579     */
580     public Iterator<E> iterator() {
581     return s.keySet().iterator();
582     }
583    
584     /**
585     * Returns an element greater than or equal to the given
586 dl 1.3 * element, or <tt>null</tt> if there is no such element.
587 dl 1.2 *
588     * @param o the value to match
589 dl 1.3 * @return an element greater than or equal to given element, or <tt>null</tt>
590 dl 1.2 * if there is no such element.
591     * @throws ClassCastException if o cannot be compared with the
592     * elements currently in the set.
593     * @throws NullPointerException if o is <tt>null</tt>
594     */
595     public E ceiling(E o) {
596     E key = o;
597     E least = s.getLeast();
598     if (least != null && s.getMap().compare(o, least) < 0)
599     key = least;
600     E k = s.getMap().ceilingKey(key);
601     return (k != null && s.inHalfOpenRange(k))? k : null;
602     }
603    
604     /**
605 dl 1.3 * Returns an element strictly less than the given element, or <tt>null</tt> if
606 dl 1.2 * there is no such element.
607     *
608     * @param o the value to match
609     * @return the greatest element less than the given element, or
610 dl 1.3 * <tt>null</tt> if there is no such element.
611 dl 1.2 * @throws ClassCastException if o cannot be compared with the
612     * elements currently in the set.
613     * @throws NullPointerException if o is <tt>null</tt>.
614     */
615     public E lower(E o) {
616     E k = s.getMap().lowerKey(o);
617     return (k != null && s.inHalfOpenRange(k))? k : null;
618     }
619    
620     /**
621 dl 1.3 * Returns an element less than or equal to the given element, or <tt>null</tt>
622 dl 1.2 * if there is no such element.
623     *
624     * @param o the value to match
625     * @return the greatest element less than or equal to given
626 dl 1.3 * element, or <tt>null</tt> if there is no such element.
627 dl 1.2 * @throws ClassCastException if o cannot be compared with the
628     * elements currently in the set.
629     * @throws NullPointerException if o is <tt>null</tt>.
630     */
631     public E floor(E o) {
632     E k = s.getMap().floorKey(o);
633     return (k != null && s.inHalfOpenRange(k))? k : null;
634     }
635    
636     /**
637 dl 1.3 * Returns an element strictly greater than the given element, or <tt>null</tt>
638 dl 1.2 * if there is no such element.
639     *
640     * @param o the value to match
641     * @return the least element greater than the given element, or
642 dl 1.3 * <tt>null</tt> if there is no such element.
643 dl 1.2 * @throws ClassCastException if o cannot be compared with the
644     * elements currently in the set.
645     * @throws NullPointerException if o is <tt>null</tt>.
646     */
647     public E higher(E o) {
648     E k;
649     E least = s.getLeast();
650     if (least != null && s.getMap().compare(o, least) < 0)
651     k = s.getMap().ceilingKey(least);
652     else
653     k = s.getMap().higherKey(o);
654     return (k != null && s.inHalfOpenRange(k))? k : null;
655     }
656    
657     /**
658     * Retrieves and removes the first (lowest) element.
659     *
660     * @return the first element, or <tt>null</tt> if empty.
661     */
662     public E pollFirst() {
663     for (;;) {
664     E k = s.lowestKey();
665     if (k == null)
666     return null;
667     if (remove(k))
668     return k;
669     }
670     }
671    
672     /**
673     * Retrieves and removes the last (highest) element.
674     *
675     * @return the last element, or <tt>null</tt> if empty.
676     */
677     public E pollLast() {
678     for (;;) {
679     E k = s.highestKey();
680     if (k == null)
681     return null;
682     if (remove(k))
683     return k;
684     }
685     }
686    
687     /**
688     * Returns the comparator used to order this set, or <tt>null</tt>
689     * if this set uses its elements natural ordering.
690     *
691     * @return the comparator used to order this set, or <tt>null</tt>
692     * if this set uses its elements natural ordering.
693     */
694     public Comparator<? super E> comparator() {
695     return s.comparator();
696     }
697    
698     /**
699     * Returns the first (lowest) element currently in this set.
700     *
701     * @return the first (lowest) element currently in this set.
702     * @throws NoSuchElementException sorted set is empty.
703     */
704     public E first() {
705     return s.firstKey();
706     }
707    
708     /**
709     * Returns the last (highest) element currently in this set.
710     *
711     * @return the last (highest) element currently in this set.
712     * @throws NoSuchElementException sorted set is empty.
713     */
714     public E last() {
715     return s.lastKey();
716     }
717    
718     /**
719     * Returns a view of the portion of this set whose elements
720     * range from <tt>fromElement</tt>, inclusive, to
721     * <tt>toElement</tt>, exclusive. (If <tt>fromElement</tt>
722     * and <tt>toElement</tt> are equal, the returned sorted set
723     * is empty.) The returned sorted set is backed by this set,
724     * so changes in the returned sorted set are reflected in this
725     * set, and vice-versa.
726     * @param fromElement low endpoint (inclusive) of the subSet.
727     * @param toElement high endpoint (exclusive) of the subSet.
728     * @return a view of the portion of this set whose elements
729     * range from <tt>fromElement</tt>, inclusive, to
730     * <tt>toElement</tt>, exclusive.
731     * @throws ClassCastException if <tt>fromElement</tt> and
732     * <tt>toElement</tt> cannot be compared to one another using
733     * this set's comparator (or, if the set has no comparator,
734     * using natural ordering).
735     * @throws IllegalArgumentException if <tt>fromElement</tt> is
736     * greater than <tt>toElement</tt> or either key is outside
737     * the range of this set.
738     * @throws NullPointerException if <tt>fromElement</tt> or
739     * <tt>toElement</tt> is <tt>null</tt>.
740     */
741     public NavigableSet<E> subSet(E fromElement,
742     E toElement) {
743     if (!s.inOpenRange(fromElement) || !s.inOpenRange(toElement))
744     throw new IllegalArgumentException("element out of range");
745     return new ConcurrentSkipListSubSet<E>(s.getMap(),
746     fromElement, toElement);
747     }
748    
749     /**
750     * Returns a view of the portion of this set whose elements are
751     * strictly less than <tt>toElement</tt>. The returned sorted set
752     * is backed by this set, so changes in the returned sorted set
753     * are reflected in this set, and vice-versa.
754     * @param toElement high endpoint (exclusive) of the headSet.
755     * @return a view of the portion of this set whose elements
756     * are strictly less than toElement.
757     * @throws ClassCastException if <tt>toElement</tt> is not
758     * compatible with this set's comparator (or, if the set has
759     * no comparator, if <tt>toElement</tt> does not implement
760     * <tt>Comparable</tt>).
761     * @throws IllegalArgumentException if <tt>toElement</tt> is
762     * outside the range of this set.
763     * @throws NullPointerException if <tt>toElement</tt> is
764     * <tt>null</tt>.
765     */
766     public NavigableSet<E> headSet(E toElement) {
767     E least = s.getLeast();
768     if (!s.inOpenRange(toElement))
769     throw new IllegalArgumentException("element out of range");
770     return new ConcurrentSkipListSubSet<E>(s.getMap(),
771     least, toElement);
772     }
773    
774     /**
775     * Returns a view of the portion of this set whose elements
776     * are greater than or equal to <tt>fromElement</tt>. The
777     * returned sorted set is backed by this set, so changes in
778     * the returned sorted set are reflected in this set, and
779     * vice-versa.
780     * @param fromElement low endpoint (inclusive) of the tailSet.
781     * @return a view of the portion of this set whose elements
782     * are greater than or equal to <tt>fromElement</tt>.
783     * @throws ClassCastException if <tt>fromElement</tt> is not
784     * compatible with this set's comparator (or, if the set has
785     * no comparator, if <tt>fromElement</tt> does not implement
786     * <tt>Comparable</tt>).
787     * @throws IllegalArgumentException if <tt>fromElement</tt> is
788     * outside the range of this set.
789     * @throws NullPointerException if <tt>fromElement</tt> is
790     * <tt>null</tt>.
791     */
792     public NavigableSet<E> tailSet(E fromElement) {
793     E fence = s.getFence();
794     if (!s.inOpenRange(fromElement))
795     throw new IllegalArgumentException("element out of range");
796     return new ConcurrentSkipListSubSet<E>(s.getMap(),
797     fromElement, fence);
798     }
799     }
800 dl 1.1 }