ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166x/ConcurrentSkipListSet.java
Revision: 1.2
Committed: Mon Sep 6 17:01:54 2004 UTC (19 years, 7 months ago) by dl
Branch: MAIN
Changes since 1.1: +377 -88 lines
Log Message:
Add Navigable interfaces for concurrent skip list classes; adjust accordingly

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