ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166x/ConcurrentSkipListSet.java
(Generate patch)

Comparing jsr166/src/jsr166x/ConcurrentSkipListSet.java (file contents):
Revision 1.1 by dl, Wed Aug 11 10:58:15 2004 UTC vs.
Revision 1.6 by dl, Tue Mar 8 17:51:57 2005 UTC

# Line 10 | Line 10 | 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>
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>
# Line 24 | Line 24 | import java.util.concurrent.*;
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
27 > * ConcurrentModificationException}, and may proceed 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 *
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
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.
33 > * 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   *
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 < * because null arguments and return values cannot be reliably
44 > * because <tt>null</tt> arguments and return values cannot be reliably
45   * distinguished from the absence of elements.
46   *
47   * @author Doug Lea
# Line 63 | Line 49 | import java.util.concurrent.*;
49   */
50   public class ConcurrentSkipListSet<E>
51      extends AbstractSet<E>
52 <    implements SortedSet<E>, Queue<E>, Cloneable, java.io.Serializable {
52 >    implements NavigableSet<E>, Cloneable, java.io.Serializable {
53  
54      private static final long serialVersionUID = -2479143111061671589L;
55  
# Line 104 | Line 90 | public class ConcurrentSkipListSet<E>
90       *
91       * @throws ClassCastException if the elements in the specified
92       * collection are not comparable, or are not mutually comparable.
93 <     * @throws NullPointerException if the specified collection is null.
93 >     * @throws NullPointerException if the specified collection is
94 >     * <tt>null</tt>.
95       */
96      public ConcurrentSkipListSet(Collection<? extends E> c) {
97          m = new ConcurrentSkipListMap<E,Object>();
# Line 116 | Line 103 | public class ConcurrentSkipListSet<E>
103       * sorted set, sorted according to the same ordering.
104       *
105       * @param s sorted set whose elements will comprise the new set.
106 <     * @throws NullPointerException if the specified sorted set is null.
106 >     * @throws NullPointerException if the specified sorted set is
107 >     * <tt>null</tt>.
108       */
109      public ConcurrentSkipListSet(SortedSet<E> s) {
110          m = new ConcurrentSkipListMap<E,Object>(s.comparator());
# Line 231 | Line 219 | public class ConcurrentSkipListSet<E>
219      public Iterator<E> iterator() {
220          return m.keyIterator();
221      }
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    }
222  
223      /**
224 <     * Retrieves and removes the first (lowest) element.
224 >     * Returns an iterator over the elements in this set.  The elements
225 >     * are returned in descending order.
226       *
227 <     * @return the least element, or <tt>null</tt> if empty.
227 >     * @return an iterator over the elements in this set.
228       */
229 <    public E poll() {
230 <        return m.removeFirstKey();
229 >    public Iterator<E> descendingIterator() {
230 >        return m.descendingKeyIterator();
231      }
232  
233 <    /**
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 <    }
233 >    /* ---------------- AbstractSet Overrides -------------- */
234  
235      /**
236 <     * Retrieves, but does not remove, the first (lowest) element,
237 <     * returning <tt>null</tt> if empty.
238 <     *
239 <     * @return the first (lowest) element, or <tt>null</tt> if empty.
240 <     */
241 <    public E peek() {
242 <        return m.lowestKey();
236 >     * Compares the specified object with this set for equality.  Returns
237 >     * <tt>true</tt> if the specified object is also a set, the two sets
238 >     * have the same size, and every member of the specified set is
239 >     * contained in this set (or equivalently, every member of this set is
240 >     * contained in the specified set).  This definition ensures that the
241 >     * equals method works properly across different implementations of the
242 >     * set interface.
243 >     *
244 >     * @param o Object to be compared for equality with this set.
245 >     * @return <tt>true</tt> if the specified Object is equal to this set.
246 >     */
247 >    public boolean equals(Object o) {
248 >        // Override AbstractSet version to avoid calling size()
249 >        if (o == this)
250 >            return true;
251 >        if (!(o instanceof Set))
252 >            return false;
253 >        Collection c = (Collection) o;
254 >        try {
255 >            return containsAll(c) && c.containsAll(this);
256 >        } catch(ClassCastException unused)   {
257 >            return false;
258 >        } catch(NullPointerException unused) {
259 >            return false;
260 >        }
261      }
262 <
262 >    
263      /**
264 <     * Retrieves, but does not remove, the first (lowest) element.
265 <     * This method differs from the <tt>peek</tt> method only in that
266 <     * it throws an exception if empty.
267 <     *
268 <     * @return the first (lowest) element.
269 <     * @throws NoSuchElementException if empty.
270 <     */
271 <    public E element() {
272 <        return m.firstKey();
273 <    }        
274 <
264 >     * Removes from this set all of its elements that are contained in
265 >     * the specified collection.  If the specified collection is also
266 >     * a set, this operation effectively modifies this set so that its
267 >     * value is the <i>asymmetric set difference</i> of the two sets.
268 >     *
269 >     * @param  c collection that defines which elements will be removed from
270 >     *           this set.
271 >     * @return <tt>true</tt> if this set changed as a result of the call.
272 >     *
273 >     * @throws ClassCastException if the types of one or more elements in this
274 >     *            set are incompatible with the specified collection
275 >     * @throws NullPointerException if the specified collection, or any
276 >     * of its elements are <tt>null</tt>.
277 >     */
278 >    public boolean removeAll(Collection<?> c) {
279 >        // Override AbstractSet version to avoid unnecessary call to size()
280 >        boolean modified = false;
281 >        for (Iterator<?> i = c.iterator(); i.hasNext(); )
282 >            if (remove(i.next()))
283 >                modified = true;
284 >        return modified;
285 >    }
286 >    
287      /* ---------------- Relational operations -------------- */
288  
289      /**
290       * Returns an element greater than or equal to the given element, or
291 <     * null if there is no such element.
291 >     * <tt>null</tt> if there is no such element.
292       *
293       * @param o the value to match
294 <     * @return an element greater than or equal to given element, or null
295 <     * if there is no such element.
294 >     * @return an element greater than or equal to given element, or
295 >     * <tt>null</tt> if there is no such element.
296       * @throws ClassCastException if o cannot be compared with the elements
297       *            currently in the set.
298       * @throws NullPointerException if o is <tt>null</tt>
# Line 309 | Line 302 | public class ConcurrentSkipListSet<E>
302      }
303  
304      /**
305 <     * Returns an element strictly less than the given element, or null if
306 <     * there is no such element.
305 >     * Returns an element strictly less than the given element, or
306 >     * <tt>null</tt> if there is no such element.
307       *
308       * @param o the value to match
309       * @return the greatest element less than the given element, or
310 <     * null if there is no such element.
310 >     * <tt>null</tt> if there is no such element.
311       * @throws ClassCastException if o cannot be compared with the elements
312       *            currently in the set.
313       * @throws NullPointerException if o is <tt>null</tt>.
# Line 324 | Line 317 | public class ConcurrentSkipListSet<E>
317      }
318  
319      /**
320 <     * Returns an element less than or equal to the given element, or null
321 <     * if there is no such element.
320 >     * Returns an element less than or equal to the given element, or
321 >     * <tt>null</tt> if there is no such element.
322       *
323       * @param o the value to match
324       * @return the greatest element less than or equal to given
325 <     * element, or null if there is no such element.
325 >     * element, or <tt>null</tt> if there is no such element.
326       * @throws ClassCastException if o cannot be compared with the elements
327       *            currently in the set.
328       * @throws NullPointerException if o is <tt>null</tt>.
# Line 339 | Line 332 | public class ConcurrentSkipListSet<E>
332      }
333  
334      /**
335 <     * Returns an element strictly greater than the given element, or null
336 <     * if there is no such element.
335 >     * Returns an element strictly greater than the given element, or
336 >     * <tt>null</tt> if there is no such element.
337       *
338       * @param o the value to match
339       * @return the least element greater than the given element, or
340 <     * null if there is no such element.
340 >     * <tt>null</tt> if there is no such element.
341       * @throws ClassCastException if o cannot be compared with the elements
342       *            currently in the set.
343       * @throws NullPointerException if o is <tt>null</tt>.
# Line 353 | Line 346 | public class ConcurrentSkipListSet<E>
346          return m.higherKey(o);
347      }
348  
349 +    /**
350 +     * Retrieves and removes the first (lowest) element.
351 +     *
352 +     * @return the least element, or <tt>null</tt> if empty.
353 +     */
354 +    public E pollFirst() {
355 +        return m.pollFirstKey();
356 +    }
357 +
358 +    /**
359 +     * Retrieves and removes the last (highest) element.
360 +     *
361 +     * @return the last element, or <tt>null</tt> if empty.
362 +     */
363 +    public E pollLast() {
364 +        return m.pollLastKey();
365 +    }
366 +
367 +
368      /* ---------------- SortedSet operations -------------- */
369  
370  
# Line 387 | Line 399 | public class ConcurrentSkipListSet<E>
399          return m.lastKey();
400      }
401  
402 +
403 +
404      /**
405       * Returns a view of the portion of this set whose elements range from
406       * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive.  (If
# Line 408 | Line 422 | public class ConcurrentSkipListSet<E>
422       * @throws NullPointerException if <tt>fromElement</tt> or
423       *         <tt>toElement</tt> is <tt>null</tt>.
424       */
425 <    public ConcurrentSkipListSubSet<E> subSet(E fromElement, E toElement) {
425 >    public NavigableSet<E> subSet(E fromElement, E toElement) {
426          return new ConcurrentSkipListSubSet<E>(m, fromElement, toElement);
427      }
428  
# Line 425 | Line 439 | public class ConcurrentSkipListSet<E>
439       *         if <tt>toElement</tt> does not implement <tt>Comparable</tt>).
440       * @throws NullPointerException if <tt>toElement</tt> is <tt>null</tt>.
441       */
442 <    public ConcurrentSkipListSubSet<E> headSet(E toElement) {
442 >    public NavigableSet<E> headSet(E toElement) {
443          return new ConcurrentSkipListSubSet<E>(m, null, toElement);
444      }
445  
# Line 444 | Line 458 | public class ConcurrentSkipListSet<E>
458       * <tt>Comparable</tt>).
459       * @throws NullPointerException if <tt>fromElement</tt> is <tt>null</tt>.
460       */
461 <    public ConcurrentSkipListSubSet<E> tailSet(E fromElement) {
461 >    public NavigableSet<E> tailSet(E fromElement) {
462          return new ConcurrentSkipListSubSet<E>(m, fromElement, null);
463      }
464 +
465 +    /**
466 +     * Subsets returned by {@link ConcurrentSkipListSet} subset operations
467 +     * represent a subrange of elements of their underlying
468 +     * sets. Instances of this class support all methods of their
469 +     * underlying sets, differing in that elements outside their range are
470 +     * ignored, and attempts to add elements outside their ranges result
471 +     * in {@link IllegalArgumentException}.  Instances of this class are
472 +     * constructed only using the <tt>subSet</tt>, <tt>headSet</tt>, and
473 +     * <tt>tailSet</tt> methods of their underlying sets.
474 +     *
475 +     */
476 +    static class ConcurrentSkipListSubSet<E>
477 +        extends AbstractSet<E>
478 +        implements NavigableSet<E>, java.io.Serializable {
479 +
480 +        private static final long serialVersionUID = -7647078645896651609L;
481 +
482 +        /** The underlying submap  */
483 +        private final ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object> s;
484 +        
485 +        /**
486 +         * Creates a new submap.
487 +         * @param fromElement inclusive least value, or <tt>null</tt> if from start
488 +         * @param toElement exclusive upper bound or <tt>null</tt> if to end
489 +         * @throws IllegalArgumentException if fromElement and toElement
490 +         * nonnull and fromElement greater than toElement
491 +         */
492 +        ConcurrentSkipListSubSet(ConcurrentSkipListMap<E,Object> map,
493 +                                 E fromElement, E toElement) {
494 +            s = new ConcurrentSkipListMap.ConcurrentSkipListSubMap<E,Object>
495 +                (map, fromElement, toElement);
496 +        }
497 +
498 +        // subsubset construction
499 +
500 +        public NavigableSet<E> subSet(E fromElement, E toElement) {
501 +            if (!s.inOpenRange(fromElement) || !s.inOpenRange(toElement))
502 +                throw new IllegalArgumentException("element out of range");
503 +            return new ConcurrentSkipListSubSet<E>(s.getMap(),
504 +                                                   fromElement, toElement);
505 +        }
506 +
507 +        public NavigableSet<E> headSet(E toElement) {
508 +            E least = s.getLeast();
509 +            if (!s.inOpenRange(toElement))
510 +                throw new IllegalArgumentException("element out of range");
511 +            return new ConcurrentSkipListSubSet<E>(s.getMap(),
512 +                                                   least, toElement);
513 +        }
514 +        
515 +        public NavigableSet<E> tailSet(E fromElement) {
516 +            E fence = s.getFence();
517 +            if (!s.inOpenRange(fromElement))
518 +                throw new IllegalArgumentException("element out of range");
519 +            return new ConcurrentSkipListSubSet<E>(s.getMap(),
520 +                                                   fromElement, fence);
521 +        }
522 +
523 +        // relays to submap methods
524 +
525 +        public int size()                 { return s.size(); }
526 +        public boolean isEmpty()          { return s.isEmpty(); }
527 +        public boolean contains(Object o) { return s.containsKey(o); }
528 +        public void clear()               { s.clear(); }
529 +        public E first()                  { return s.firstKey(); }
530 +        public E last()                   { return s.lastKey(); }
531 +        public E ceiling(E o)             { return s.ceilingKey(o); }
532 +        public E lower(E o)               { return s.lowerKey(o); }
533 +        public E floor(E o)               { return s.floorKey(o); }
534 +        public E higher(E o)              { return s.higherKey(o); }
535 +        public boolean remove(Object o) { return s.remove(o)==Boolean.TRUE; }
536 +        public boolean add(E o)       { return s.put(o, Boolean.TRUE)==null; }
537 +        public Comparator<? super E> comparator() { return s.comparator(); }
538 +        public Iterator<E> iterator()     { return s.keySet().iterator(); }
539 +        public Iterator<E> descendingIterator() {
540 +            return s.descendingKeySet().iterator();
541 +        }
542 +        public E pollFirst() {
543 +            Map.Entry<E,?> e = s.pollFirstEntry();
544 +            return (e == null)? null : e.getKey();
545 +        }
546 +        public E pollLast() {
547 +            Map.Entry<E,?> e = s.pollLastEntry();
548 +            return (e == null)? null : e.getKey();
549 +        }
550 +
551 +    }
552   }    

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines