ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentSkipListSet.java
Revision: 1.8
Committed: Mon May 2 18:38:53 2005 UTC (19 years, 1 month ago) by jsr166
Branch: MAIN
Changes since 1.7: +24 -24 lines
Log Message:
remove trailing whitespace

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 java.util.concurrent;
8     import java.util.*;
9    
10     /**
11     * A scalable concurrent {@link NavigableSet} implementation based on
12     * a {@link ConcurrentSkipListMap}. This class maintains a set in
13     * ascending order, sorted according to the <i>natural order</i> for
14 dl 1.3 * the elements' class (see {@link Comparable}), or by the comparator
15 dl 1.1 * provided at creation time, depending on which constructor is
16     * used.<p>
17     *
18     * This implementation provides expected average <i>log(n)</i> time
19     * cost for the <tt>contains</tt>, <tt>add</tt>, and <tt>remove</tt>
20     * operations and their variants. Insertion, removal, and access
21     * operations safely execute concurrently by multiple
22     * threads. Iterators are <i>weakly consistent</i>, returning elements
23     * reflecting the state of the set at some point at or since the
24     * creation of the iterator. They do <em>not</em> throw {@link
25 dl 1.2 * ConcurrentModificationException}, and may proceed concurrently with
26 dl 1.1 * other operations.
27     *
28     * <p>Beware that, unlike in most collections, the <tt>size</tt>
29     * 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. Additionally, the
32     * bulk operations <tt>addAll</tt>, <tt>removeAll</tt>,
33 dl 1.3 * <tt>retainAll</tt>, and <tt>containsAll</tt> are <em>not</em>
34 dl 1.1 * guaranteed to be performed atomically. For example, an iterator
35     * operating concurrently with an <tt>addAll</tt> operation might view
36     * only some of the added elements.
37     *
38     * <p>This class and its iterators implement all of the
39     * <em>optional</em> methods of the {@link Set} and {@link Iterator}
40     * interfaces. Like most other concurrent collection implementations,
41     * this class does not permit the use of <tt>null</tt> elements.
42     * because <tt>null</tt> arguments and return values cannot be reliably
43     * distinguished from the absence of elements.
44     *
45     * @author Doug Lea
46     * @param <E> the type of elements maintained by this set
47     */
48     public class ConcurrentSkipListSet<E>
49     extends AbstractSet<E>
50     implements NavigableSet<E>, Cloneable, java.io.Serializable {
51    
52     private static final long serialVersionUID = -2479143111061671589L;
53    
54     /**
55     * The underlying map. Uses Boolean.TRUE as value for each
56     * element. Note that this class relies on default serialization,
57     * which is a little wasteful in saving all of the useless value
58     * fields of underlying map, but enables this field to be declared
59     * final, which is necessary for thread safety.
60     */
61 jsr166 1.8 private final ConcurrentSkipListMap<E,Object> m;
62 dl 1.1
63     /**
64     * Constructs a new, empty set, sorted according to the elements' natural
65 jsr166 1.8 * order.
66 dl 1.1 */
67     public ConcurrentSkipListSet() {
68     m = new ConcurrentSkipListMap<E,Object>();
69     }
70    
71     /**
72     * Constructs a new, empty set, sorted according to the specified
73 jsr166 1.8 * comparator.
74 dl 1.1 *
75     * @param c the comparator that will be used to sort this set. A
76     * <tt>null</tt> value indicates that the elements' <i>natural
77     * ordering</i> should be used.
78     */
79     public ConcurrentSkipListSet(Comparator<? super E> c) {
80     m = new ConcurrentSkipListMap<E,Object>(c);
81     }
82    
83     /**
84     * Constructs a new set containing the elements in the specified
85     * collection, sorted according to the elements' <i>natural order</i>.
86     *
87     * @param c The elements that will comprise the new set.
88     *
89     * @throws ClassCastException if the elements in the specified
90     * collection are not comparable, or are not mutually comparable.
91     * @throws NullPointerException if the specified collection is
92     * <tt>null</tt>.
93     */
94     public ConcurrentSkipListSet(Collection<? extends E> c) {
95     m = new ConcurrentSkipListMap<E,Object>();
96     addAll(c);
97     }
98    
99     /**
100     * Constructs a new set containing the same elements as the specified
101     * sorted set, sorted according to the same ordering.
102     *
103     * @param s sorted set whose elements will comprise the new set.
104     * @throws NullPointerException if the specified sorted set is
105     * <tt>null</tt>.
106     */
107     public ConcurrentSkipListSet(SortedSet<E> s) {
108     m = new ConcurrentSkipListMap<E,Object>(s.comparator());
109     addAll(s);
110     }
111    
112     /**
113     * Returns a shallow copy of this set. (The elements themselves
114     * are not cloned.)
115     *
116     * @return a shallow copy of this set.
117     */
118 jsr166 1.7 public ConcurrentSkipListSet<E> clone() {
119 dl 1.1 ConcurrentSkipListSet<E> clone = null;
120     try {
121     clone = (ConcurrentSkipListSet<E>) super.clone();
122     } catch (CloneNotSupportedException e) {
123     throw new InternalError();
124     }
125    
126     clone.m.initialize();
127     clone.addAll(this);
128     return clone;
129     }
130    
131     /* ---------------- Set operations -------------- */
132    
133     /**
134     * Returns the number of elements in this set. If this set
135     * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
136     * returns <tt>Integer.MAX_VALUE</tt>.
137     *
138     * <p>Beware that, unlike in most collections, this method is
139     * <em>NOT</em> a constant-time operation. Because of the
140     * asynchronous nature of these sets, determining the current
141     * number of elements requires traversing them all to count them.
142     * Additionally, it is possible for the size to change during
143     * execution of this method, in which case the returned result
144     * will be inaccurate. Thus, this method is typically not very
145     * useful in concurrent applications.
146     *
147     * @return the number of elements in this set.
148     */
149     public int size() {
150     return m.size();
151     }
152    
153     /**
154     * Returns <tt>true</tt> if this set contains no elements.
155     * @return <tt>true</tt> if this set contains no elements.
156     */
157     public boolean isEmpty() {
158     return m.isEmpty();
159     }
160    
161     /**
162     * Returns <tt>true</tt> if this set contains the specified element.
163     *
164     * @param o the object to be checked for containment in this set.
165     * @return <tt>true</tt> if this set contains the specified element.
166     *
167     * @throws ClassCastException if the specified object cannot be compared
168     * with the elements currently in the set.
169     * @throws NullPointerException if o is <tt>null</tt>.
170     */
171     public boolean contains(Object o) {
172     return m.containsKey(o);
173     }
174    
175     /**
176     * Adds the specified element to this set if it is not already present.
177     *
178 jsr166 1.5 * @param e element to be added to this set.
179 dl 1.1 * @return <tt>true</tt> if the set did not already contain the specified
180     * element.
181     *
182     * @throws ClassCastException if the specified object cannot be compared
183     * with the elements currently in the set.
184 jsr166 1.5 * @throws NullPointerException if e is <tt>null</tt>.
185 dl 1.1 */
186 jsr166 1.5 public boolean add(E e) {
187     return m.putIfAbsent(e, Boolean.TRUE) == null;
188 dl 1.1 }
189    
190     /**
191     * Removes the specified element from this set if it is present.
192     *
193     * @param o object to be removed from this set, if present.
194     * @return <tt>true</tt> if the set contained the specified 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 remove(Object o) {
201     return m.removep(o);
202     }
203    
204     /**
205     * Removes all of the elements from this set.
206     */
207     public void clear() {
208     m.clear();
209     }
210    
211     /**
212     * Returns an iterator over the elements in this set. The elements
213     * are returned in ascending order.
214     *
215     * @return an iterator over the elements in this set.
216     */
217     public Iterator<E> iterator() {
218     return m.keyIterator();
219     }
220    
221     /**
222     * Returns an iterator over the elements in this set. The elements
223     * are returned in descending order.
224     *
225     * @return an iterator over the elements in this set.
226     */
227     public Iterator<E> descendingIterator() {
228     return m.descendingKeyIterator();
229     }
230    
231     /* ---------------- AbstractSet Overrides -------------- */
232    
233     /**
234     * Compares the specified object with this set for equality. Returns
235     * <tt>true</tt> if the specified object is also a set, the two sets
236     * have the same size, and every member of the specified set is
237     * contained in this set (or equivalently, every member of this set is
238     * contained in the specified set). This definition ensures that the
239     * equals method works properly across different implementations of the
240     * set interface.
241     *
242     * @param o Object to be compared for equality with this set.
243     * @return <tt>true</tt> if the specified Object is equal to this set.
244     */
245     public boolean equals(Object o) {
246     // Override AbstractSet version to avoid calling size()
247     if (o == this)
248     return true;
249     if (!(o instanceof Set))
250     return false;
251     Collection c = (Collection) o;
252     try {
253     return containsAll(c) && c.containsAll(this);
254 jsr166 1.6 } catch (ClassCastException unused) {
255 dl 1.1 return false;
256 jsr166 1.6 } catch (NullPointerException unused) {
257 dl 1.1 return false;
258     }
259     }
260 jsr166 1.8
261 dl 1.1 /**
262     * Removes from this set all of its elements that are contained in
263     * the specified collection. If the specified collection is also
264     * a set, this operation effectively modifies this set so that its
265     * value is the <i>asymmetric set difference</i> of the two sets.
266     *
267     * @param c collection that defines which elements will be removed from
268     * this set.
269     * @return <tt>true</tt> if this set changed as a result of the call.
270 jsr166 1.8 *
271 dl 1.1 * @throws ClassCastException if the types of one or more elements in this
272     * set are incompatible with the specified collection
273     * @throws NullPointerException if the specified collection, or any
274     * of its elements are <tt>null</tt>.
275     */
276     public boolean removeAll(Collection<?> c) {
277     // Override AbstractSet version to avoid unnecessary call to size()
278     boolean modified = false;
279     for (Iterator<?> i = c.iterator(); i.hasNext(); )
280     if (remove(i.next()))
281     modified = true;
282     return modified;
283     }
284 jsr166 1.8
285 dl 1.1 /* ---------------- Relational operations -------------- */
286    
287     /**
288     * Returns an element greater than or equal to the given element, or
289     * <tt>null</tt> if there is no such element.
290 jsr166 1.8 *
291 jsr166 1.5 * @param e the value to match
292 dl 1.1 * @return an element greater than or equal to given element, or
293     * <tt>null</tt> if there is no such element.
294 jsr166 1.5 * @throws ClassCastException if e cannot be compared with the elements
295 dl 1.1 * currently in the set.
296 jsr166 1.5 * @throws NullPointerException if e is <tt>null</tt>
297 dl 1.1 */
298 jsr166 1.5 public E ceiling(E e) {
299     return m.ceilingKey(e);
300 dl 1.1 }
301    
302     /**
303     * Returns an element strictly less than the given element, or
304     * <tt>null</tt> if there is no such element.
305 jsr166 1.8 *
306 jsr166 1.5 * @param e the value to match
307 dl 1.1 * @return the greatest element less than the given element, or
308     * <tt>null</tt> if there is no such element.
309 jsr166 1.5 * @throws ClassCastException if e cannot be compared with the elements
310 dl 1.1 * currently in the set.
311 jsr166 1.5 * @throws NullPointerException if e is <tt>null</tt>.
312 dl 1.1 */
313 jsr166 1.5 public E lower(E e) {
314     return m.lowerKey(e);
315 dl 1.1 }
316    
317     /**
318     * Returns an element less than or equal to the given element, or
319     * <tt>null</tt> if there is no such element.
320 jsr166 1.8 *
321 jsr166 1.5 * @param e the value to match
322 dl 1.1 * @return the greatest element less than or equal to given
323     * element, or <tt>null</tt> if there is no such element.
324 jsr166 1.5 * @throws ClassCastException if e cannot be compared with the elements
325 dl 1.1 * currently in the set.
326 jsr166 1.5 * @throws NullPointerException if e is <tt>null</tt>.
327 dl 1.1 */
328 jsr166 1.5 public E floor(E e) {
329     return m.floorKey(e);
330 dl 1.1 }
331    
332     /**
333     * Returns an element strictly greater than the given element, or
334     * <tt>null</tt> if there is no such element.
335 jsr166 1.8 *
336 jsr166 1.5 * @param e the value to match
337 dl 1.1 * @return the least element greater than the given element, or
338     * <tt>null</tt> if there is no such element.
339 jsr166 1.5 * @throws ClassCastException if e cannot be compared with the elements
340 dl 1.1 * currently in the set.
341 jsr166 1.5 * @throws NullPointerException if e is <tt>null</tt>.
342 dl 1.1 */
343 jsr166 1.5 public E higher(E e) {
344     return m.higherKey(e);
345 dl 1.1 }
346    
347     /**
348     * Retrieves and removes the first (lowest) element.
349     *
350     * @return the least element, or <tt>null</tt> if empty.
351     */
352     public E pollFirst() {
353     return m.pollFirstKey();
354     }
355    
356     /**
357     * Retrieves and removes the last (highest) element.
358     *
359     * @return the last element, or <tt>null</tt> if empty.
360     */
361     public E pollLast() {
362     return m.pollLastKey();
363     }
364    
365    
366     /* ---------------- SortedSet operations -------------- */
367    
368    
369     /**
370     * Returns the comparator used to order this set, or <tt>null</tt>
371     * if this set uses its elements natural ordering.
372     *
373     * @return the comparator used to order this set, or <tt>null</tt>
374     * if this set uses its elements natural ordering.
375     */
376     public Comparator<? super E> comparator() {
377     return m.comparator();
378     }
379    
380     /**
381     * Returns the first (lowest) element currently in this set.
382     *
383     * @return the first (lowest) element currently in this set.
384     * @throws NoSuchElementException sorted set is empty.
385     */
386     public E first() {
387     return m.firstKey();
388     }
389    
390     /**
391     * Returns the last (highest) element currently in this set.
392     *
393     * @return the last (highest) element currently in this set.
394     * @throws NoSuchElementException sorted set is empty.
395     */
396     public E last() {
397     return m.lastKey();
398     }
399    
400     /**
401     * Returns a view of the portion of this set whose elements range from
402     * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive. (If
403     * <tt>fromElement</tt> and <tt>toElement</tt> are equal, the returned
404 dl 1.3 * navigable set is empty.) The returned navigable set is backed by this set,
405     * so changes in the returned navigable set are reflected in this set, and
406 jsr166 1.8 * vice-versa.
407 dl 1.1 * @param fromElement low endpoint (inclusive) of the subSet.
408     * @param toElement high endpoint (exclusive) of the subSet.
409     * @return a view of the portion of this set whose elements range from
410     * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
411     * exclusive.
412     * @throws ClassCastException if <tt>fromElement</tt> and
413     * <tt>toElement</tt> cannot be compared to one another using
414     * this set's comparator (or, if the set has no comparator,
415     * using natural ordering).
416     * @throws IllegalArgumentException if <tt>fromElement</tt> is
417     * greater than <tt>toElement</tt>.
418     * @throws NullPointerException if <tt>fromElement</tt> or
419     * <tt>toElement</tt> is <tt>null</tt>.
420     */
421 dl 1.3 public NavigableSet<E> navigableSubSet(E fromElement, E toElement) {
422 dl 1.1 return new ConcurrentSkipListSubSet<E>(m, fromElement, toElement);
423     }
424    
425     /**
426     * Returns a view of the portion of this set whose elements are strictly
427 dl 1.3 * less than <tt>toElement</tt>. The returned navigable set is backed by
428     * this set, so changes in the returned navigable set are reflected in this
429 jsr166 1.8 * set, and vice-versa.
430 dl 1.1 * @param toElement high endpoint (exclusive) of the headSet.
431     * @return a view of the portion of this set whose elements are strictly
432     * less than toElement.
433     * @throws ClassCastException if <tt>toElement</tt> is not compatible
434     * with this set's comparator (or, if the set has no comparator,
435     * if <tt>toElement</tt> does not implement <tt>Comparable</tt>).
436     * @throws NullPointerException if <tt>toElement</tt> is <tt>null</tt>.
437     */
438 dl 1.3 public NavigableSet<E> navigableHeadSet(E toElement) {
439 dl 1.1 return new ConcurrentSkipListSubSet<E>(m, null, toElement);
440     }
441    
442    
443     /**
444     * Returns a view of the portion of this set whose elements are
445     * greater than or equal to <tt>fromElement</tt>. The returned
446 dl 1.3 * navigable set is backed by this set, so changes in the returned
447     * navigable set are reflected in this set, and vice-versa.
448 dl 1.1 * @param fromElement low endpoint (inclusive) of the tailSet.
449     * @return a view of the portion of this set whose elements are
450     * greater than or equal to <tt>fromElement</tt>.
451     * @throws ClassCastException if <tt>fromElement</tt> is not
452     * compatible with this set's comparator (or, if the set has no
453     * comparator, if <tt>fromElement</tt> does not implement
454     * <tt>Comparable</tt>).
455     * @throws NullPointerException if <tt>fromElement</tt> is <tt>null</tt>.
456     */
457 dl 1.3 public NavigableSet<E> navigableTailSet(E fromElement) {
458     return new ConcurrentSkipListSubSet<E>(m, fromElement, null);
459     }
460    
461    
462     /**
463     * Equivalent to <tt>navigableSubSet</tt> but with a return
464     * type conforming to the <tt>SortedSet</tt> interface.
465     * @param fromElement low endpoint (inclusive) of the subSet.
466     * @param toElement high endpoint (exclusive) of the subSet.
467     * @return a view of the portion of this set whose elements range from
468     * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
469     * exclusive.
470     * @throws ClassCastException if <tt>fromElement</tt> and
471     * <tt>toElement</tt> cannot be compared to one another using
472     * this set's comparator (or, if the set has no comparator,
473     * using natural ordering).
474     * @throws IllegalArgumentException if <tt>fromElement</tt> is
475     * greater than <tt>toElement</tt>.
476     * @throws NullPointerException if <tt>fromElement</tt> or
477     * <tt>toElement</tt> is <tt>null</tt>.
478     */
479     public SortedSet<E> subSet(E fromElement, E toElement) {
480 dl 1.4 return navigableSubSet(fromElement, toElement);
481 dl 1.3 }
482    
483     /**
484     * Equivalent to <tt>navigableHeadSet</tt> but with a return
485     * type conforming to the <tt>SortedSet</tt> interface.
486     * @param toElement high endpoint (exclusive) of the headSet.
487     * @return a view of the portion of this set whose elements are strictly
488     * less than toElement.
489     * @throws ClassCastException if <tt>toElement</tt> is not compatible
490     * with this set's comparator (or, if the set has no comparator,
491     * if <tt>toElement</tt> does not implement <tt>Comparable</tt>).
492     * @throws NullPointerException if <tt>toElement</tt> is <tt>null</tt>.
493     */
494     public SortedSet<E> headSet(E toElement) {
495 dl 1.4 return navigableHeadSet(toElement);
496 dl 1.3 }
497    
498    
499     /**
500     * Equivalent to <tt>navigableTailSet</tt> but with a return
501     * type conforming to the <tt>SortedSet</tt> interface.
502     * @param fromElement low endpoint (inclusive) of the tailSet.
503     * @return a view of the portion of this set whose elements are
504     * greater than or equal to <tt>fromElement</tt>.
505     * @throws ClassCastException if <tt>fromElement</tt> is not
506     * compatible with this set's comparator (or, if the set has no
507     * comparator, if <tt>fromElement</tt> does not implement
508     * <tt>Comparable</tt>).
509     * @throws NullPointerException if <tt>fromElement</tt> is <tt>null</tt>.
510     */
511     public SortedSet<E> tailSet(E fromElement) {
512 dl 1.4 return navigableTailSet(fromElement);
513 dl 1.1 }
514    
515     /**
516     * Subsets returned by {@link ConcurrentSkipListSet} subset operations
517     * represent a subrange of elements of their underlying
518     * sets. Instances of this class support all methods of their
519     * underlying sets, differing in that elements outside their range are
520     * ignored, and attempts to add elements outside their ranges result
521     * in {@link IllegalArgumentException}. Instances of this class are
522     * constructed only using the <tt>subSet</tt>, <tt>headSet</tt>, and
523     * <tt>tailSet</tt> methods of their underlying sets.
524     *
525     */
526 jsr166 1.8 static class ConcurrentSkipListSubSet<E>
527     extends AbstractSet<E>
528 dl 1.1 implements NavigableSet<E>, java.io.Serializable {
529    
530     private static final long serialVersionUID = -7647078645896651609L;
531    
532     /** The underlying submap */
533     private final ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object> s;
534 jsr166 1.8
535 dl 1.1 /**
536 jsr166 1.8 * Creates a new submap.
537 dl 1.1 * @param fromElement inclusive least value, or <tt>null</tt> if from start
538     * @param toElement exclusive upper bound or <tt>null</tt> if to end
539     * @throws IllegalArgumentException if fromElement and toElement
540     * nonnull and fromElement greater than toElement
541     */
542 jsr166 1.8 ConcurrentSkipListSubSet(ConcurrentSkipListMap<E,Object> map,
543 dl 1.1 E fromElement, E toElement) {
544     s = new ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object>
545     (map, fromElement, toElement);
546     }
547    
548     // subsubset construction
549    
550 dl 1.3 public NavigableSet<E> navigableSubSet(E fromElement, E toElement) {
551 dl 1.1 if (!s.inOpenRange(fromElement) || !s.inOpenRange(toElement))
552     throw new IllegalArgumentException("element out of range");
553 jsr166 1.8 return new ConcurrentSkipListSubSet<E>(s.getMap(),
554 dl 1.1 fromElement, toElement);
555     }
556    
557 dl 1.3 public NavigableSet<E> navigableHeadSet(E toElement) {
558 dl 1.1 E least = s.getLeast();
559     if (!s.inOpenRange(toElement))
560     throw new IllegalArgumentException("element out of range");
561 jsr166 1.8 return new ConcurrentSkipListSubSet<E>(s.getMap(),
562 dl 1.1 least, toElement);
563     }
564 jsr166 1.8
565 dl 1.3 public NavigableSet<E> navigableTailSet(E fromElement) {
566 dl 1.1 E fence = s.getFence();
567     if (!s.inOpenRange(fromElement))
568     throw new IllegalArgumentException("element out of range");
569 jsr166 1.8 return new ConcurrentSkipListSubSet<E>(s.getMap(),
570 dl 1.1 fromElement, fence);
571     }
572    
573 dl 1.3 public SortedSet<E> subSet(E fromElement, E toElement) {
574     return navigableSubSet(fromElement, toElement);
575     }
576    
577     public SortedSet<E> headSet(E toElement) {
578     return navigableHeadSet(toElement);
579     }
580 jsr166 1.8
581 dl 1.3 public SortedSet<E> tailSet(E fromElement) {
582     return navigableTailSet(fromElement);
583     }
584    
585 dl 1.1 // relays to submap methods
586    
587     public int size() { return s.size(); }
588     public boolean isEmpty() { return s.isEmpty(); }
589     public boolean contains(Object o) { return s.containsKey(o); }
590     public void clear() { s.clear(); }
591     public E first() { return s.firstKey(); }
592     public E last() { return s.lastKey(); }
593 jsr166 1.5 public E ceiling(E e) { return s.ceilingKey(e); }
594     public E lower(E e) { return s.lowerKey(e); }
595     public E floor(E e) { return s.floorKey(e); }
596     public E higher(E e) { return s.higherKey(e); }
597 dl 1.1 public boolean remove(Object o) { return s.remove(o)==Boolean.TRUE; }
598 jsr166 1.5 public boolean add(E e) { return s.put(e, Boolean.TRUE)==null; }
599 dl 1.1 public Comparator<? super E> comparator() { return s.comparator(); }
600     public Iterator<E> iterator() { return s.keySet().iterator(); }
601     public Iterator<E> descendingIterator() {
602     return s.descendingKeySet().iterator();
603     }
604 jsr166 1.8 public E pollFirst() {
605 dl 1.1 Map.Entry<E,?> e = s.pollFirstEntry();
606     return (e == null)? null : e.getKey();
607     }
608     public E pollLast() {
609     Map.Entry<E,?> e = s.pollLastEntry();
610     return (e == null)? null : e.getKey();
611     }
612    
613     }
614 jsr166 1.8 }