/[classpath]/classpath/java/util/Collections.java
ViewVC logotype

Diff of /classpath/java/util/Collections.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.19 by ericb, Thu Sep 20 23:38:12 2001 UTC revision 1.20 by ericb, Fri Oct 19 00:17:44 2001 UTC
# Line 25  This exception does not however invalida Line 25  This exception does not however invalida
25  executable file might be covered by the GNU General Public License. */  executable file might be covered by the GNU General Public License. */
26    
27    
 // TO DO:  
 // ~ Serialization is very much broken. Blame Sun for not specifying it.  
 // ~ The synchronized* and unmodifiable* methods don't have doc-comments.  
   
28  package java.util;  package java.util;
29    
30  import java.io.Serializable;  import java.io.Serializable;
# Line 40  import java.io.Serializable; Line 36  import java.io.Serializable;
36   * are unaware of collections, a method to return a list which consists of   * are unaware of collections, a method to return a list which consists of
37   * multiple copies of one element, and methods which "wrap" collections to give   * multiple copies of one element, and methods which "wrap" collections to give
38   * them extra properties, such as thread-safety and unmodifiability.   * them extra properties, such as thread-safety and unmodifiability.
39     * <p>
40     *
41     * All methods which take a collection throw a {@link NullPointerException} if
42     * that collection is null. Algorithms which can change a collection may, but
43     * are not required, to throw the {@link UnsupportedOperationException} that
44     * the underlying collection would throw during an attempt at modification.
45     * For example,
46     * <code>Collections.singleton("").addAll(Collections.EMPTY_SET)<code>
47     * does not throw a exception, even though addAll is an unsupported operation
48     * on a singleton; the reason for this is that addAll did not attempt to
49     * modify the set.
50     *
51     * @author Original author unknown
52     * @author Eric Blake <ebb9@email.byu.edu>
53     * @see Collection
54     * @see Set
55     * @see List
56     * @see Map
57     * @see Arrays
58     * @since 1.2
59     * @status updated to 1.4
60   */   */
61  public class Collections  public class Collections
62  {  {
63    /**    /**
64       * Constant used to decide cutoff for when a non-RandomAccess list should
65       * be treated as sequential-access. Basically, quadratic behavior is
66       * acceptible for small lists when the overhead is so small in the first
67       * place. I arbitrarily set it to 16, so it may need some tuning.
68       */
69      private static final int LARGE_LIST_SIZE = 16;
70    
71      /**
72       * Determines if a list should be treated as a sequential-access one.
73       * Rather than the old method of JDK 1.3 of assuming only instanceof
74       * AbstractSequentialList should be sequential, this uses the new method
75       * of JDK 1.4 of assuming anything that does NOT implement RandomAccess
76       * and exceeds a large (unspecified) size should be sequential.
77       *
78       * @param l the list to check
79       * @return true if it should be treated as sequential-access
80       */
81      private static boolean isSequential(List l)
82      {
83        return ! (l instanceof RandomAccess) && l.size() > LARGE_LIST_SIZE;
84      }
85    
86      /**
87     * This class is non-instantiable.     * This class is non-instantiable.
88     */     */
89    private Collections()    private Collections()
# Line 51  public class Collections Line 91  public class Collections
91    }    }
92    
93    /**    /**
94     * An immutable, empty Set.     * An immutable, serializable, empty Set.
95     * Note: This implementation isn't Serializable, although it should be by the     * @see Serializable
96     * spec.     */
97      public static final Set EMPTY_SET = new EmptySet();
98    
99      /**
100       * The implementation of {@link #EMPTY_SET}. This class name is required
101       * for compatibility with Sun's JDK serializability.
102       *
103       * @author Eric Blake <ebb9@email.byu.edu>
104     */     */
105    public static final Set EMPTY_SET = new AbstractSet()    private static final class EmptySet extends AbstractSet
106        implements Serializable
107    {    {
108        /**
109         * Compatible with JDK 1.4.
110         */
111        private static final long serialVersionUID = 1582296315990362920L;
112    
113        /**
114         * A private constructor adds overhead.
115         */
116        EmptySet()
117        {
118        }
119    
120        /**
121         * The size: always 0!
122         */
123      public int size()      public int size()
124      {      {
125        return 0;        return 0;
126      }      }
127    
128      // This is really cheating! I think it's perfectly valid, though - the      /**
129      // more conventional code is here, commented out, in case anyone disagrees.       * Returns an iterator that does not iterate.
130         */
131        // This is really cheating! I think it's perfectly valid, though.
132      public Iterator iterator()      public Iterator iterator()
133      {      {
134        return EMPTY_LIST.iterator();        return EMPTY_LIST.iterator();
135      }      }
136    
137      // public Iterator iterator() {      // The remaining methods are optional, but provide a performance
138      //   return new Iterator() {      // advantage by not allocating unnecessary iterators in AbstractSet.
139      //      /**
140      //     public boolean hasNext() {       * The empty set never contains anything.
141      //       return false;       */
142      //     }      public boolean contains(Object o)
143      //      {
144      //     public Object next() {        return false;
145      //       throw new NoSuchElementException();      }
146      //     }  
147      //      /**
148      //     public void remove() {       * This is true only if the given collection is also empty.
149      //       throw new UnsupportedOperationException();       */
150      //     }      public boolean containsAll(Collection c)
151      //   };      {
152      // }        return c.isEmpty();
153        }
154    };  
155        /**
156    /**       * Equal only if the other set is empty.
157     * An immutable, empty List.       */
158     * Note: This implementation isn't serializable, although it should be by the      public boolean equals(Object o)
159     * spec.      {
160          return o instanceof Set && ((Set) o).isEmpty();
161        }
162    
163        /**
164         * The hashcode is always 0.
165         */
166        public int hashCode()
167        {
168          return 0;
169        }
170    
171        /**
172         * Always succeeds with false result.
173         */
174        public boolean remove(Object o)
175        {
176          return false;
177        }
178    
179        /**
180         * Always succeeds with false result.
181         */
182        public boolean removeAll(Collection c)
183        {
184          return false;
185        }
186    
187        /**
188         * Always succeeds with false result.
189         */
190        public boolean retainAll(Collection c)
191        {
192          return false;
193        }
194    
195        /**
196         * The array is always empty.
197         */
198        public Object[] toArray()
199        {
200          return new Object[0];
201        }
202    
203        /**
204         * We don't even need to use reflection!
205         */
206        public Object[] toArray(Object[] a)
207        {
208          if (a.length > 0)
209            a[0] = null;
210          return a;
211        }
212    
213        /**
214         * The string never changes.
215         */
216        public String toString()
217        {
218          return "[]";
219        }
220      } // class EmptySet
221    
222      /**
223       * An immutable, serializable, empty List, which implements RandomAccess.
224       * @see Serializable
225       * @see RandomAccess
226     */     */
227    public static final List EMPTY_LIST = new AbstractList()    public static final List EMPTY_LIST = new EmptyList();
228    
229      /**
230       * The implementation of {@link #EMPTY_LIST}. This class name is required
231       * for compatibility with Sun's JDK serializability.
232       *
233       * @author Eric Blake <ebb9@email.byu.edu>
234       */
235      private static final class EmptyList extends AbstractList
236        implements Serializable, RandomAccess
237    {    {
238        /**
239         * Compatible with JDK 1.4.
240         */
241        private static final long serialVersionUID = 8842843931221139166L;
242    
243        /**
244         * A private constructor adds overhead.
245         */
246        EmptyList()
247        {
248        }
249    
250        /**
251         * The size is always 0.
252         */
253      public int size()      public int size()
254      {      {
255        return 0;        return 0;
256      }      }
257    
258        /**
259         * No matter the index, it is out of bounds.
260         */
261      public Object get(int index)      public Object get(int index)
262      {      {
263        throw new IndexOutOfBoundsException();        throw new IndexOutOfBoundsException();
264      }      }
265    };  
266        // The remaining methods are optional, but provide a performance
267        // advantage by not allocating unnecessary iterators in AbstractList.
268        /**
269         * Never contains anything.
270         */
271        public boolean contains(Object o)
272        {
273          return false;
274        }
275    
276        /**
277         * This is true only if the given collection is also empty.
278         */
279        public boolean containsAll(Collection c)
280        {
281          return c.isEmpty();
282        }
283    
284        /**
285         * Equal only if the other set is empty.
286         */
287        public boolean equals(Object o)
288        {
289          return o instanceof List && ((List) o).isEmpty();
290        }
291    
292        /**
293         * The hashcode is always 1.
294         */
295        public int hashCode()
296        {
297          return 1;
298        }
299    
300        /**
301         * Returns -1.
302         */
303        public int indexOf(Object o)
304        {
305          return -1;
306        }
307    
308        /**
309         * Returns -1.
310         */
311        public int lastIndexOf(Object o)
312        {
313          return -1;
314        }
315    
316        /**
317         * Always succeeds with false result.
318         */
319        public boolean remove(Object o)
320        {
321          return false;
322        }
323    
324        /**
325         * Always succeeds with false result.
326         */
327        public boolean removeAll(Collection c)
328        {
329          return false;
330        }
331    
332        /**
333         * Always succeeds with false result.
334         */
335        public boolean retainAll(Collection c)
336        {
337          return false;
338        }
339    
340        /**
341         * The array is always empty.
342         */
343        public Object[] toArray()
344        {
345          return new Object[0];
346        }
347    
348        /**
349         * We don't even need to use reflection!
350         */
351        public Object[] toArray(Object[] a)
352        {
353          if (a.length > 0)
354            a[0] = null;
355          return a;
356        }
357    
358        /**
359         * The string never changes.
360         */
361        public String toString()
362        {
363          return "[]";
364        }
365      } // class EmptyList
366    
367    /**    /**
368     * An immutable, empty Map.     * An immutable, serializable, empty Map.
369     * Note: This implementation isn't serializable, although it should be by the     * @see Serializable
    * spec.  
370     */     */
371    public static final Map EMPTY_MAP = new AbstractMap()    public static final Map EMPTY_MAP = new EmptyMap();
372    
373      /**
374       * The implementation of {@link #EMPTY_MAP}. This class name is required
375       * for compatibility with Sun's JDK serializability.
376       *
377       * @author Eric Blake <ebb9@email.byu.edu>
378       */
379      private static final class EmptyMap extends AbstractMap
380        implements Serializable
381    {    {
382        /**
383         * Compatible with JDK 1.4.
384         */
385        private static final long serialVersionUID = 6428348081105594320L;
386    
387        /**
388         * A private constructor adds overhead.
389         */
390        EmptyMap()
391        {
392        }
393    
394        /**
395         * There are no entries.
396         */
397      public Set entrySet()      public Set entrySet()
398      {      {
399        return EMPTY_SET;        return EMPTY_SET;
400      }      }
   };  
401    
402        // The remaining methods are optional, but provide a performance
403        // advantage by not allocating unnecessary iterators in AbstractMap.
404        /**
405         * No entries!
406         */
407        public boolean containsKey(Object key)
408        {
409          return false;
410        }
411    
412        /**
413         * No entries!
414         */
415        public boolean containsValue(Object value)
416        {
417          return false;
418        }
419    
420        /**
421         * Equal to all empty maps.
422         */
423        public boolean equals(Object o)
424        {
425          return o instanceof Map && ((Map) o).isEmpty();
426        }
427    
428        /**
429         * No mappings, so this returns null.
430         */
431        public Object get(Object o)
432        {
433          return null;
434        }
435    
436        /**
437         * The hashcode is always 0.
438         */
439        public int hashCode()
440        {
441          return 0;
442        }
443    
444        /**
445         * No entries.
446         */
447        public Set keySet()
448        {
449          return EMPTY_SET;
450        }
451    
452        /**
453         * Remove always succeeds, with null result.
454         */
455        public Object remove(Object o)
456        {
457          return null;
458        }
459    
460        /**
461         * Size is always 0.
462         */
463        public int size()
464        {
465          return 0;
466        }
467    
468        /**
469         * No entries. Technically, EMPTY_SET, while more specific than a general
470         * Collection, will work. Besides, that's what the JDK uses!
471         */
472        public Collection values()
473        {
474          return EMPTY_SET;
475        }
476    
477        /**
478         * The string never changes.
479         */
480        public String toString()
481        {
482          return "[]";
483        }
484      } // class EmptyMap
485    
486    
487    /**    /**
488     * Compare two objects with or without a Comparator. If c is null, uses the     * Compare two objects with or without a Comparator. If c is null, uses the
489     * natural ordering. Slightly slower than doing it inline if the JVM isn't     * natural ordering. Slightly slower than doing it inline if the JVM isn't
490     * clever, but worth it for removing a duplicate of the search code.     * clever, but worth it for removing a duplicate of the search code.
491     * Note: This same code is used in Arrays (for sort as well as search)     * Note: This code is also used in Arrays (for sort as well as search).
492     */     */
493    private static int compare(Object o1, Object o2, Comparator c)    static final int compare(Object o1, Object o2, Comparator c)
494    {    {
495      if (c == null)      return c == null ? ((Comparable) o1).compareTo(o2) : c.compare(o1, o2);
       {  
         return ((Comparable) o1).compareTo(o2);  
       }  
     else  
       {  
         return c.compare(o1, o2);  
       }  
   }  
   
   /**  
    * The hard work for the search routines. If the Comparator given is null,  
    * uses the natural ordering of the elements.  
    */  
   private static int search(List l, Object key, final Comparator c)  
   {  
     int pos = 0;  
   
     // We use a linear search using an iterator if we can guess that the list  
     // is sequential-access.  
     if (l instanceof AbstractSequentialList)  
       {  
         ListIterator itr = l.listIterator();  
         for (int i = l.size() - 1; i >= 0; --i)  
           {  
             final int d = compare(key, itr.next(), c);  
             if (d == 0)  
               {  
                 return pos;  
               }  
             else if (d < 0)  
               {  
                 return -pos - 1;  
               }  
             pos++;  
           }  
   
         // We assume the list is random-access, and use a binary search  
       }  
     else  
       {  
         int low = 0;  
         int hi = l.size() - 1;  
         while (low <= hi)  
           {  
             pos = (low + hi) >> 1;  
             final int d = compare(key, l.get(pos), c);  
             if (d == 0)  
               {  
                 return pos;  
               }  
             else if (d < 0)  
               {  
                 hi = pos - 1;  
               }  
             else  
               {  
                 low = ++pos;    // This gets the insertion point right on the last loop  
               }  
           }  
       }  
   
     // If we failed to find it, we do the same whichever search we did.  
     return -pos - 1;  
496    }    }
497    
498    /**    /**
499     * Perform a binary search of a List for a key, using the natural ordering of     * Perform a binary search of a List for a key, using the natural ordering of
500     * the elements. The list must be sorted (as by the sort() method) - if it is     * the elements. The list must be sorted (as by the sort() method) - if it is
501     * not, the behaviour of this method is undefined, and may be an infinite     * not, the behavior of this method is undefined, and may be an infinite
502     * loop. Further, the key must be comparable with every item in the list. If     * loop. Further, the key must be comparable with every item in the list. If
503     * the list contains the key more than once, any one of them may be found. To     * the list contains the key more than once, any one of them may be found.
504     * avoid pathological behaviour on sequential-access lists, a linear search     * <p>
505     * is used if (l instanceof AbstractSequentialList). Note: although the     *
506       * This algorithm behaves in log(n) time for {@link RandomAccess} lists,
507       * and uses a linear search with O(n) link traversals and log(n) comparisons
508       * with {@link AbstractSequentialList} lists. Note: although the
509     * specification allows for an infinite loop if the list is unsorted, it will     * specification allows for an infinite loop if the list is unsorted, it will
510     * not happen in this (Classpath) implementation.     * not happen in this (Classpath) implementation.
511     *     *
512     * @param l the list to search (must be sorted)     * @param l the list to search (must be sorted)
513     * @param key the value to search for     * @param key the value to search for
514     * @returns the index at which the key was found, or -n-1 if it was not     * @return the index at which the key was found, or -n-1 if it was not
515     *   found, where n is the index of the first value higher than key or     *         found, where n is the index of the first value higher than key or
516     *   a.length if there is no such value.     *         a.length if there is no such value
517     * @exception ClassCastException if key could not be compared with one of the     * @throws ClassCastException if key could not be compared with one of the
518     *   elements of l     *         elements of l
519     * @exception NullPointerException if a null element has compareTo called     * @throws NullPointerException if a null element has compareTo called
520       * @see #sort(List)
521     */     */
522    public static int binarySearch(List l, Object key)    public static int binarySearch(List l, Object key)
523    {    {
524      return search(l, key, null);      return binarySearch(l, key, null);
525    }    }
526    
527    /**    /**
528     * Perform a binary search of a List for a key, using a supplied Comparator.     * Perform a binary search of a List for a key, using a supplied Comparator.
529     * The list must be sorted (as by the sort() method with the same Comparator)     * The list must be sorted (as by the sort() method with the same Comparator)
530     * - if it is not, the behaviour of this method is undefined, and may be an     * - if it is not, the behavior of this method is undefined, and may be an
531     * infinite loop. Further, the key must be comparable with every item in the     * infinite loop. Further, the key must be comparable with every item in the
532     * list. If the list contains the key more than once, any one of them may be     * list. If the list contains the key more than once, any one of them may be
533     * found. To avoid pathological behaviour on sequential-access lists, a     * found. If the comparator is null, the elements' natural ordering is used.
534     * linear search is used if (l instanceof AbstractSequentialList). Note:     * <p>
535     * although the specification allows for an infinite loop if the list is     *
536     * unsorted, it will not happen in this (Classpath) implementation.     * This algorithm behaves in log(n) time for {@link RandomAccess} lists,
537       * and uses a linear search with O(n) link traversals and log(n) comparisons
538       * with {@link AbstractSequentialList} lists. Note: although the
539       * specification allows for an infinite loop if the list is unsorted, it will
540       * not happen in this (Classpath) implementation.
541     *     *
542     * @param l the list to search (must be sorted)     * @param l the list to search (must be sorted)
543     * @param key the value to search for     * @param key the value to search for
544     * @param c the comparator by which the list is sorted     * @param c the comparator by which the list is sorted
545     * @returns the index at which the key was found, or -n-1 if it was not     * @return the index at which the key was found, or -n-1 if it was not
546     *   found, where n is the index of the first value higher than key or     *         found, where n is the index of the first value higher than key or
547     *   a.length if there is no such value.     *         a.length if there is no such value
548     * @exception ClassCastException if key could not be compared with one of the     * @throws ClassCastException if key could not be compared with one of the
549     *   elements of l     *         elements of l
550       * @throws NullPointerException if a null element is compared with natural
551       *         ordering (only possible when c is null)
552       * @see #sort(List, Comparator)
553     */     */
554    public static int binarySearch(List l, Object key, Comparator c)    public static int binarySearch(List l, Object key, Comparator c)
555    {    {
556      if (c == null)      int pos = 0;
557        int low = 0;
558        int hi = l.size() - 1;
559    
560        // We use a linear search with log(n) comparisons using an iterator
561        // if the list is sequential-access.
562        if (isSequential(l))
563          {
564            ListIterator itr = l.listIterator();
565            int i = 0;
566            while (low <= hi)
567              {
568                pos = (low + hi) >> 1;
569                if (i < pos)
570                  for ( ; i != pos; i++, itr.next());
571                else
572                  for ( ; i != pos; i--, itr.previous());
573                final int d = compare(key, itr.next(), c);
574                if (d == 0)
575                  return pos;
576                else if (d < 0)
577                  hi = pos - 1;
578                else
579                  // This gets the insertion point right on the last loop
580                  low = ++pos;
581              }
582          }
583        else
584        {        {
585          throw new NullPointerException();          while (low <= hi)
586              {
587                pos = (low + hi) >> 1;
588                final int d = compare(key, l.get(pos), c);
589                if (d == 0)
590                  return pos;
591                else if (d < 0)
592                  hi = pos - 1;
593                else
594                  // This gets the insertion point right on the last loop
595                  low = ++pos;
596              }
597        }        }
598      return search(l, key, c);  
599        // If we failed to find it, we do the same whichever search we did.
600        return -pos - 1;
601    }    }
602    
603    /**    /**
# Line 252  public class Collections Line 605  public class Collections
605     * source list, the remaining elements are unaffected. This method runs in     * source list, the remaining elements are unaffected. This method runs in
606     * linear time.     * linear time.
607     *     *
608     * @param dest the destination list.     * @param dest the destination list
609     * @param source the source list.     * @param source the source list
610     * @exception IndexOutOfBoundsException if the destination list is shorter     * @throws IndexOutOfBoundsException if the destination list is shorter
611     *   than the source list (the elements that can be copied will be, prior to     *         than the source list (the destination will be unmodified)
612     *   the exception being thrown).     * @throws UnsupportedOperationException if dest.listIterator() does not
613     * @exception UnsupportedOperationException if dest.listIterator() does not     *         support the set operation
    *   support the set operation.  
614     */     */
615    public static void copy(List dest, List source)    public static void copy(List dest, List source)
616    {    {
617        int pos = source.size();
618        if (dest.size() < pos)
619          throw new IndexOutOfBoundsException("Source does not fit in dest");
620    
621      Iterator i1 = source.iterator();      Iterator i1 = source.iterator();
622      ListIterator i2 = dest.listIterator();      ListIterator i2 = dest.listIterator();
623    
624      try      while (--pos >= 0)
625        {        {
626          for (int i = source.size() - 1; i >= 0; --i)          i2.next();
627            {          i2.set(i1.next());
             i2.next();  
             i2.set(i1.next());  
           }  
       }  
     catch (NoSuchElementException x)  
       {  
         throw new IndexOutOfBoundsException("Source doesn't fit in dest.");        
628        }        }
629    }    }
630    
# Line 284  public class Collections Line 633  public class Collections
633     * with legacy APIs that require an Enumeration as input.     * with legacy APIs that require an Enumeration as input.
634     *     *
635     * @param c the Collection to iterate over     * @param c the Collection to iterate over
636     * @returns an Enumeration backed by an Iterator over c     * @return an Enumeration backed by an Iterator over c
637     */     */
638    public static Enumeration enumeration(Collection c)    public static Enumeration enumeration(Collection c)
639    {    {
# Line 308  public class Collections Line 657  public class Collections
657     *     *
658     * @param l the list to fill.     * @param l the list to fill.
659     * @param val the object to vill the list with.     * @param val the object to vill the list with.
660     * @exception UnsupportedOperationException if l.listIterator() does not     * @throws UnsupportedOperationException if l.listIterator() does not
661     *   support the set operation.     *         support the set operation.
662     */     */
663    public static void fill(List l, Object val)    public static void fill(List l, Object val)
664    {    {
# Line 322  public class Collections Line 671  public class Collections
671    }    }
672    
673    /**    /**
674       * Returns the starting index where the specified sublist first occurs
675       * in a larger list, or -1 if there is no matching position. If
676       * <code>target.size() &gt; source.size()</code>, this returns -1,
677       * otherwise this implementation uses brute force, checking for
678       * <code>source.sublist(i, i + target.size()).equals(target)</code>
679       * for all possible i.
680       *
681       * @param source the list to search
682       * @param target the sublist to search for
683       * @return the index where found, or -1
684       * @since 1.4
685       */
686      public static int indexOfSubList(List source, List target)
687      {
688        int ssize = source.size();
689        for (int i = 0, j = target.size(); j <= ssize; i++, j++)
690          if (source.subList(i, j).equals(target))
691            return i;
692        return -1;
693      }
694    
695      /**
696       * Returns the starting index where the specified sublist last occurs
697       * in a larger list, or -1 if there is no matching position. If
698       * <code>target.size() &gt; source.size()</code>, this returns -1,
699       * otherwise this implementation uses brute force, checking for
700       * <code>source.sublist(i, i + target.size()).equals(target)</code>
701       * for all possible i.
702       *
703       * @param source the list to search
704       * @param target the sublist to search for
705       * @return the index where found, or -1
706       * @since 1.4
707       */
708      public static int lastIndexOfSubList(List source, List target)
709      {
710        int ssize = source.size();
711        for (int i = ssize - target.size(), j = ssize; i >= 0; i--, j--)
712          if (source.subList(i, j).equals(target))
713            return i;
714        return -1;
715      }
716    
717      /**
718       * Returns an array list holding the elements visited by a given
719       * Enumeration. This method exists for interoperatbility between legacy
720       * APIs and the new Collection API.
721       *
722       * @param e the enumeration to put in a list
723       * @return a list containing the enumeration elements
724       * @see ArrayList
725       * @since 1.4
726       */
727      public static List list(Enumeration e)
728      {
729        List l = new ArrayList();
730        while (e.hasMoreElements())
731          l.add(e.nextElement());
732        return l;
733      }
734    
735      /**
736     * Find the maximum element in a Collection, according to the natural     * Find the maximum element in a Collection, according to the natural
737     * ordering of the elements. This implementation iterates over the     * ordering of the elements. This implementation iterates over the
738     * Collection, so it works in linear time.     * Collection, so it works in linear time.
739     *     *
740     * @param c the Collection to find the maximum element of     * @param c the Collection to find the maximum element of
741     * @returns the maximum element of c     * @return the maximum element of c
742     * @exception NoSuchElementException if c is empty     * @exception NoSuchElementException if c is empty
743     * @exception ClassCastException if elements in c are not mutually comparable     * @exception ClassCastException if elements in c are not mutually comparable
744     * @exception NullPointerException if null.compareTo is called     * @exception NullPointerException if null.compareTo is called
745     */     */
746    public static Object max(Collection c)    public static Object max(Collection c)
747    {    {
748      Iterator itr = c.iterator();      return max(c, null);
     Comparable max = (Comparable) itr.next();   // throws NoSuchElementException  
     int csize = c.size();  
     for (int i = 1; i < csize; i++)  
       {  
         Object o = itr.next();  
         if (max.compareTo(o) < 0)  
           {  
             max = (Comparable) o;  
           }  
       }  
     return max;  
749    }    }
750    
751    /**    /**
# Line 354  public class Collections Line 754  public class Collections
754     * works in linear time.     * works in linear time.
755     *     *
756     * @param c the Collection to find the maximum element of     * @param c the Collection to find the maximum element of
757     * @param order the Comparator to order the elements by     * @param order the Comparator to order the elements by, or null for natural
758     * @returns the maximum element of c     *        ordering
759     * @exception NoSuchElementException if c is empty     * @return the maximum element of c
760     * @exception ClassCastException if elements in c are not mutually comparable     * @throws NoSuchElementException if c is empty
761       * @throws ClassCastException if elements in c are not mutually comparable
762       * @throws NullPointerException if null is compared by natural ordering
763       *        (only possible when order is null)
764     */     */
765    public static Object max(Collection c, Comparator order)    public static Object max(Collection c, Comparator order)
766    {    {
767      Iterator itr = c.iterator();      Iterator itr = c.iterator();
768      Object max = itr.next();    // throws NoSuchElementException      Object max = itr.next(); // throws NoSuchElementException
769      int csize = c.size();      int csize = c.size();
770      for (int i = 1; i < csize; i++)      for (int i = 1; i < csize; i++)
771        {        {
772          Object o = itr.next();          Object o = itr.next();
773          if (order.compare(max, o) < 0)          if (compare(max, o, order) < 0)
774            max = o;            max = o;
775        }        }
776      return max;      return max;
# Line 379  public class Collections Line 782  public class Collections
782     * Collection, so it works in linear time.     * Collection, so it works in linear time.
783     *     *
784     * @param c the Collection to find the minimum element of     * @param c the Collection to find the minimum element of
785     * @returns the minimum element of c     * @return the minimum element of c
786     * @exception NoSuchElementException if c is empty     * @throws NoSuchElementException if c is empty
787     * @exception ClassCastException if elements in c are not mutually comparable     * @throws ClassCastException if elements in c are not mutually comparable
788     * @exception NullPointerException if null.compareTo is called     * @throws NullPointerException if null.compareTo is called
789     */     */
790    public static Object min(Collection c)    public static Object min(Collection c)
791    {    {
792      Iterator itr = c.iterator();      return min(c, null);
     Comparable min = (Comparable) itr.next();   // throws NoSuchElementException  
     int csize = c.size();  
     for (int i = 1; i < csize; i++)  
       {  
         Object o = itr.next();  
         if (min.compareTo(o) > 0)  
           min = (Comparable) o;  
       }  
     return min;  
793    }    }
794    
795    /**    /**
# Line 404  public class Collections Line 798  public class Collections
798     * works in linear time.     * works in linear time.
799     *     *
800     * @param c the Collection to find the minimum element of     * @param c the Collection to find the minimum element of
801     * @param order the Comparator to order the elements by     * @param order the Comparator to order the elements by, or null for natural
802     * @returns the minimum element of c     *        ordering
803     * @exception NoSuchElementException if c is empty     * @return the minimum element of c
804     * @exception ClassCastException if elements in c are not mutually comparable     * @throws NoSuchElementException if c is empty
805       * @throws ClassCastException if elements in c are not mutually comparable
806       * @throws NullPointerException if null is compared by natural ordering
807       *        (only possible when order is null)
808     */     */
809    public static Object min(Collection c, Comparator order)    public static Object min(Collection c, Comparator order)
810    {    {
# Line 417  public class Collections Line 814  public class Collections
814      for (int i = 1; i < csize; i++)      for (int i = 1; i < csize; i++)
815        {        {
816          Object o = itr.next();          Object o = itr.next();
817          if (order.compare(min, o) > 0)          if (compare(min, o, order) > 0)
818            min = o;            min = o;
819        }        }
820      return min;      return min;
# Line 426  public class Collections Line 823  public class Collections
823    /**    /**
824     * Creates an immutable list consisting of the same object repeated n times.     * Creates an immutable list consisting of the same object repeated n times.
825     * The returned object is tiny, consisting of only a single reference to the     * The returned object is tiny, consisting of only a single reference to the
826     * object and a count of the number of elements. It is Serializable.     * object and a count of the number of elements. It is Serializable, and
827       * implements RandomAccess. You can use it in tandem with List.addAll for
828       * fast list construction.
829     *     *
830     * @param n the number of times to repeat the object     * @param n the number of times to repeat the object
831     * @param o the object to repeat     * @param o the object to repeat
832     * @returns a List consisting of n copies of o     * @return a List consisting of n copies of o
833     * @throws IllegalArgumentException if n < 0     * @throws IllegalArgumentException if n &lt; 0
834       * @see List#addAll(Collection)
835       * @see Serializable
836       * @see RandomAccess
837     */     */
   // It's not Serializable, because the serialized form is unspecced.  
   // Also I'm only assuming that it should be because I don't think it's  
   // stated - I just would be amazed if it isn't...  
838    public static List nCopies(final int n, final Object o)    public static List nCopies(final int n, final Object o)
839    {    {
840      // Check for insane arguments      return new CopiesList(n, o);
841      if (n < 0)    }
842        {  
843      /**
844       * The implementation of {@link #nCopies(int, Object)}. This class name
845       * is required for compatibility with Sun's JDK serializability.
846       *
847       * @author Eric Blake <ebb9@email.byu.edu>
848       */
849      private static final class CopiesList extends AbstractList
850        implements Serializable, RandomAccess
851      {
852        /**
853         * Compatible with JDK 1.4.
854         */
855        private static final long serialVersionUID = 2739099268398711800L;
856    
857        /**
858         * The count of elements in this list.
859         * @serial the list size
860         */
861        private final int n;
862    
863        /**
864         * The repeated list element.
865         * @serial the list contents
866         */
867        private final Object element;
868    
869        /**
870         * Constructs the list.
871         *
872         * @param n the count
873         * @param o the object
874         * @throws IllegalArgumentException if n &lt; 0
875         */
876        CopiesList(int n, Object o)
877        {
878          if (n < 0)
879          throw new IllegalArgumentException();          throw new IllegalArgumentException();
880        }        this.n = n;
881          element = o;
882        }
883    
884      // Create a minimal implementation of List      /**
885      return new AbstractList()       * The size is fixed.
886         */
887        public int size()
888      {      {
889        public int size()        return n;
890        {      }
         return n;  
       }  
891    
892        public Object get(int index)      /**
893        {       * The same element is returned.
894          if (index < 0 || index >= n)       */
895            {      public Object get(int index)
896              throw new IndexOutOfBoundsException();      {
897            }        if (index < 0 || index >= n)
898          return o;          throw new IndexOutOfBoundsException();
899        }        return element;
900      };      }
901    
902        // The remaining methods are optional, but provide a performance
903        // advantage by not allocating unnecessary iterators in AbstractList.
904        /**
905         * This list only contains one element.
906         */
907        public boolean contains(Object o)
908        {
909          return n > 0 && equals(element, o);
910        }
911    
912        /**
913         * The index is either 0 or -1.
914         */
915        public int indexOf(Object o)
916        {
917          return n > 0 && equals(element, o) ? 0 : -1;
918        }
919    
920        /**
921         * The index is either n-1 or -1.
922         */
923        public int lastIndexOf(Object o)
924        {
925          return equals(element, o) ? n - 1 : -1;
926        }
927    
928        /**
929         * A subList is just another CopiesList.
930         */
931        public List subList(int from, int to)
932        {
933          if (from < 0 || to > n)
934            throw new IndexOutOfBoundsException();
935          return new CopiesList(to - from, element);
936        }
937    
938        /**
939         * The array is easy.
940         */
941        public Object[] toArray()
942        {
943          Object[] a = new Object[n];
944          Arrays.fill(a, element);
945          return a;
946        }
947    
948        /**
949         * The string is easy to generate.
950         */
951        public String toString()
952        {
953          StringBuffer r = new StringBuffer("{");
954          for (int i = n - 1; --i > 0; )
955            r.append(element).append(", ");
956          r.append(element).append("}");
957          return r.toString();
958        }
959      } // class CopiesList
960    
961      /**
962       * Replace all instances of one object with another in the specified list.
963       * The list does not change size. An element e is replaced if
964       * <code>oldval == null ? e == null : oldval.equals(e)</code>.
965       *
966       * @param list the list to iterate over
967       * @param oldval the element to replace
968       * @param newval the new value for the element
969       * @return true if a replacement occurred
970       * @throws UnsupportedOperationException if the list iterator does not allow
971       *         for the set operation
972       * @throws ClassCastException newval is of a type which cannot be added
973       *         to the list
974       * @throws IllegalArgumentException some other aspect of newval stops
975       *         it being added to the list
976       * @since 1.4
977       */
978      public static boolean replaceAll(List list, Object oldval, Object newval)
979      {
980        ListIterator itr = list.listIterator();
981        boolean replace_occured = false;
982        for (int i = list.size(); --i >= 0; )
983          if (AbstractCollection.equals(oldval, itr.next()))
984            {
985              itr.set(newval);
986              replace_occured = true;
987            }
988        return replace_occured;
989    }    }
990    
991    /**    /**
992     * Reverse a given list. This method works in linear time.     * Reverse a given list. This method works in linear time.
993     *     *
994     * @param l the list to reverse.     * @param l the list to reverse
995     * @exception UnsupportedOperationException if l.listIterator() does not     * @throws UnsupportedOperationException if l.listIterator() does not
996     *   support the set operation.     *         support the set operation
997     */     */
998    public static void reverse(List l)    public static void reverse(List l)
999    {    {
1000      ListIterator i1 = l.listIterator();      ListIterator i1 = l.listIterator();
1001      int pos1 = 0;      int pos1 = 1;
1002      int pos2 = l.size();      int pos2 = l.size();
1003      ListIterator i2 = l.listIterator(pos2);      ListIterator i2 = l.listIterator(pos2);
1004      while (pos1 < pos2)      while (pos1 < pos2)
# Line 486  public class Collections Line 1011  public class Collections
1011        }        }
1012    }    }
1013    
1014    static class ReverseComparator implements Comparator, Serializable    /**
1015       * Get a comparator that implements the reverse of natural ordering. In
1016       * other words, this sorts Comparable objects opposite of how their
1017       * compareTo method would sort. This makes it easy to sort into reverse
1018       * order, by simply passing Collections.reverseOrder() to the sort method.
1019       * The return value of this method is Serializable.
1020       *
1021       * @return a comparator that imposes reverse natural ordering
1022       * @see Comparable
1023       * @see Serializable
1024       */
1025      public static Comparator reverseOrder()
1026    {    {
1027        return rcInstance;
1028      }
1029    
1030      /**
1031       * The object for {@link #reverseOrder()}.
1032       */
1033      static private final ReverseComparator rcInstance = new ReverseComparator();
1034    
1035      /**
1036       * The implementation of {@link #reverseOrder()}. This class name
1037       * is required for compatibility with Sun's JDK serializability.
1038       *
1039       * @author Eric Blake <ebb9@email.byu.edu>
1040       */
1041      private static final class ReverseComparator
1042        implements Comparator, Serializable
1043      {
1044        /**
1045         * Compatible with JDK 1.4.
1046         */
1047        static private final long serialVersionUID = 7207038068494060240L;
1048    
1049        /**
1050         * A private constructor adds overhead.
1051         */
1052        ReverseComparator()
1053        {
1054        }
1055    
1056        /**
1057         * Compare two objects in reverse natural order.
1058         *
1059         * @param a the first object
1060         * @param b the second object
1061         * @return &lt;, ==, or &gt; 0 according to b.compareTo(a)
1062         */
1063      public int compare(Object a, Object b)      public int compare(Object a, Object b)
1064      {      {
1065        return -((Comparable) a).compareTo(b);        return ((Comparable) b).compareTo(a);
1066      }      }
1067    }    }
1068      
   static ReverseComparator rcInstance = new ReverseComparator();  
     
1069    /**    /**
1070     * Get a comparator that implements the reverse of natural ordering. This is     * Rotate the elements in a list by a specified distance. After calling this
1071     * intended to make it easy to sort into reverse order, by simply passing     * method, the element now at index <code>i</code> was formerly at index
1072     * Collections.reverseOrder() to the sort method. The return value of this     * <code>(i - distance) mod list.size()</code>. The list size is unchanged.
1073     * method is Serializable.     * <p>
1074     */     *
1075    public static Comparator reverseOrder()     * For example, suppose a list contains <code>[t, a, n, k, s]</code>. After
1076    {     * either <code>Collections.rotate(l, 4)</code> or
1077      return rcInstance;     * <code>Collections.rotate(l, -1)</code>, the new contents are
1078       * <code>[s, t, a, n, k]</code>. This can be applied to sublists to rotate
1079       * just a portion of the list. For example, to move element <code>a</code>
1080       * forward two positions in the original example, use
1081       * <code>Collections.rotate(l.subList(1, 3+1), -1)</code>, which will
1082       * result in <code>[t, n, k, a, s]</code>.
1083       * <p>
1084       *
1085       * If the list is small or implements {@link RandomAccess}, the
1086       * implementation exchanges the first element to its destination, then the
1087       * displaced element, and so on until a circuit has been completed. The
1088       * process is repeated if needed on the second element, and so forth, until
1089       * all elements have been swapped.  For large non-random lists, the
1090       * implementation breaks the list into two sublists at index
1091       * <code>-distance mod size</code>, calls {@link #reverse(List)} on the
1092       * pieces, then reverses the overall list.
1093       *
1094       * @param list the list to rotate
1095       * @param distance the distance to rotate by; unrestricted in value
1096       * @throws UnsupportedOperationException if the list does not support set
1097       * @since 1.4
1098       */
1099      public static void rotate(List list, int distance)
1100      {
1101        int size = list.size();
1102        distance %= size;
1103        if (distance == 0)
1104          return;
1105        if (distance < 0)
1106          distance += size;
1107    
1108        if (isSequential(list))
1109          {
1110            reverse(list);
1111            reverse(list.subList(0, distance));
1112            reverse(list.subList(distance, size));
1113          }
1114        else
1115          {
1116            // Determine the least common multiple of distance and size, as there
1117            // are (distance / LCM) loops to cycle through.
1118            int a = size;
1119            int lcm = distance;
1120            int b = a % lcm;
1121            while (b != 0)
1122              {
1123                a = lcm;
1124                lcm = b;
1125                b = a % lcm;
1126              }
1127    
1128            // Now, make the swaps. We must take the remainder every time through
1129            // the inner loop so that we don't overflow i to negative values.
1130            while (--lcm >= 0)
1131              {
1132                Object o = list.get(lcm);
1133                for (int i = lcm + distance; i != lcm; i = (i + distance) % size)
1134                  o = list.set(i, o);
1135                list.set(lcm, o);
1136              }
1137          }
1138    }    }
1139    
1140    /**    /**
1141     * Shuffle a list according to a default source of randomness. The algorithm     * Shuffle a list according to a default source of randomness. The algorithm
1142     * used would result in a perfectly fair shuffle (that is, each element would     * used iterates backwards over the list, swapping each element with an
1143     * have an equal chance of ending up in any position) with a perfect source     * element randomly selected from the elements in positions less than or
1144     * of randomness; in practice the results are merely very close to perfect.     * equal to it (using r.nextInt(int)).
1145     * <p>     * <p>
1146     * This method operates in linear time on a random-access list, but may take     *
1147     * quadratic time on a sequential-access list.     * This algorithm would result in a perfectly fair shuffle (that is, each
1148     * Note: this (classpath) implementation will never take quadratic time, but     * element would have an equal chance of ending up in any position) if r were
1149     * it does make a copy of the list. This is in line with the behaviour of the     * a perfect source of randomness. In practice the results are merely very
1150     * sort methods and seems preferable.     * close to perfect.
1151     *     * <p>
1152     * @param l the list to shuffle.     *
1153     * @exception UnsupportedOperationException if l.listIterator() does not     * This method operates in linear time. To do this on large lists which do
1154     *   support the set operation.     * not implement {@link RandomAccess}, a temporary array is used to acheive
1155       * this speed, since it would be quadratic access otherwise.
1156       *
1157       * @param l the list to shuffle
1158       * @throws UnsupportedOperationException if l.listIterator() does not
1159       *         support the set operation
1160     */     */
1161    public static void shuffle(List l)    public static void shuffle(List l)
1162    {    {
# Line 536  public class Collections Line 1171  public class Collections
1171      shuffle(l, defaultRandom);      shuffle(l, defaultRandom);
1172    }    }
1173    
1174    /** Cache a single Random object for use by shuffle(List). This improves    /**
1175      * performance as well as ensuring that sequential calls to shuffle() will     * Cache a single Random object for use by shuffle(List). This improves
1176      * not result in the same shuffle order occuring: the resolution of     * performance as well as ensuring that sequential calls to shuffle() will
1177      * System.currentTimeMillis() is not sufficient to guarantee a unique seed.     * not result in the same shuffle order occuring: the resolution of
1178      */     * System.currentTimeMillis() is not sufficient to guarantee a unique seed.
1179       */
1180    private static Random defaultRandom = null;    private static Random defaultRandom = null;
1181    
1182    /**    /**
# Line 549  public class Collections Line 1185  public class Collections
1185     * element randomly selected from the elements in positions less than or     * element randomly selected from the elements in positions less than or
1186     * equal to it (using r.nextInt(int)).     * equal to it (using r.nextInt(int)).
1187     * <p>     * <p>
1188       *
1189     * This algorithm would result in a perfectly fair shuffle (that is, each     * This algorithm would result in a perfectly fair shuffle (that is, each
1190     * element would have an equal chance of ending up in any position) if r were     * element would have an equal chance of ending up in any position) if r were
1191     * a perfect source of randomness. In practise (eg if r = new Random()) the     * a perfect source of randomness. In practise (eg if r = new Random()) the
1192     * results are merely very close to perfect.     * results are merely very close to perfect.
1193     * <p>     * <p>
1194     * This method operates in linear time on a random-access list, but may take     *
1195     * quadratic time on a sequential-access list.     * This method operates in linear time. To do this on large lists which do
1196     * Note: this (classpath) implementation will never take quadratic time, but     * not implement {@link RandomAccess}, a temporary array is used to acheive
1197     * it does make a copy of the list. This is in line with the behaviour of the     * this speed, since it would be quadratic access otherwise.
1198     * sort methods and seems preferable.     *
1199     *     * @param l the list to shuffle
1200     * @param l the list to shuffle.     * @param r the source of randomness to use for the shuffle
1201     * @param r the source of randomness to use for the shuffle.     * @throws UnsupportedOperationException if l.listIterator() does not
1202     * @exception UnsupportedOperationException if l.listIterator() does not     *         support the set operation
    *   support the set operation.  
1203     */     */
1204    public static void shuffle(List l, Random r)    public static void shuffle(List l, Random r)
1205    {    {
     Object[] a = l.toArray();   // Dump l into an array  
1206      int lsize = l.size();      int lsize = l.size();
1207      ListIterator i = l.listIterator(lsize);      ListIterator i = l.listIterator(lsize);
1208        boolean sequential = isSequential(l);
1209        Object[] a = null; // stores a copy of the list for the sequential case
1210    
1211        if (sequential)
1212          a = l.toArray();
1213    
1214      // Iterate backwards over l      for (int pos = lsize - 1; pos > 0; --pos)
     for (int pos = lsize - 1; pos >= 0; --pos)  
1215        {        {
1216          // Obtain a random position to swap with. pos + 1 is used so that the          // Obtain a random position to swap with. pos + 1 is used so that the
1217          // range of the random number includes the current position.          // range of the random number includes the current position.
1218          int swap = r.nextInt(pos + 1);          int swap = r.nextInt(pos + 1);
1219    
1220          // Swap the swapth element of the array with the next element of the          // Swap the desired element.
1221          // list.          Object o;
1222          Object o = a[swap];          if (sequential)
1223          a[swap] = a[pos];            {
1224          a[pos] = o;              o = a[swap];
1225                a[swap] = i.previous();
1226              }
1227            else
1228              o = l.set(swap, i.previous());
1229    
         // Set the element in the original list accordingly.  
         i.previous();  
1230          i.set(o);          i.set(o);
1231        }        }
1232    }    }
1233    
1234    
1235    /**    /**
1236     * Obtain an immutable Set consisting of a single element. The return value     * Obtain an immutable Set consisting of a single element. The return value
1237     * of this method is Serializable.     * of this method is Serializable.
1238     *     *
1239     * @param o the single element.     * @param o the single element
1240     * @return an immutable Set containing only o.     * @return an immutable Set containing only o
1241       * @see Serializable
1242       */
1243      public static Set singleton(Object o)
1244      {
1245        return new SingletonSet(o);
1246      }
1247    
1248      /**
1249       * The implementation of {@link #singleton(Object)}. This class name
1250       * is required for compatibility with Sun's JDK serializability.
1251       *
1252       * @author Eric Blake <ebb9@email.byu.edu>
1253     */     */
1254    // It's not serializable because the spec is broken.    private static final class SingletonSet extends AbstractSet
1255    public static Set singleton(final Object o)      implements Serializable
1256    {    {
1257      return new AbstractSet()      /**
1258         * Compatible with JDK 1.4.
1259         */
1260        private static final long serialVersionUID = 3193687207550431679L;
1261    
1262    
1263        /**
1264         * The single element.
1265         * @serial the singleton
1266         */
1267        private final Object element;
1268    
1269        /**
1270         * Construct a singleton.
1271         * @param o the element
1272         */
1273        SingletonSet(Object o)
1274      {      {
1275        public int size()        element = o;
1276        {      }
         return 1;  
       }  
1277    
1278        public Iterator iterator()      /**
1279         * The size: always 1!
1280         */
1281        public int size()
1282        {
1283          return 1;
1284        }
1285    
1286        /**
1287         * Returns an iterator over the lone element.
1288         */
1289        public Iterator iterator()
1290        {
1291          return new Iterator()
1292        {        {
1293          return new Iterator()          private boolean hasNext = true;
         {  
           private boolean hasNext = true;  
1294    
1295            public boolean hasNext()          public boolean hasNext()
1296            {          {
1297              return hasNext;            return hasNext;
1298            }          }
1299    
1300            public Object next()
1301            {
1302              if (hasNext)
1303              {
1304                hasNext = false;
1305                return element;
1306              }
1307              else
1308                throw new NoSuchElementException();
1309            }
1310    
1311            public void remove()
1312            {
1313              throw new UnsupportedOperationException();
1314            }
1315          };
1316        }
1317    
1318            public Object next()      // The remaining methods are optional, but provide a performance
1319            {      // advantage by not allocating unnecessary iterators in AbstractSet.
1320              if (hasNext)      /**
1321                {       * The set only contains one element.
1322                  hasNext = false;       */
1323                  return o;      public boolean contains(Object o)
1324                }      {
1325              else        return equals(element, o);
1326                {      }
                 throw new NoSuchElementException();  
               }  
           }  
1327    
1328            public void remove()      /**
1329            {       * This is true if the other collection only contains the element.
1330              throw new UnsupportedOperationException();       */
1331            }      public boolean containsAll(Collection c)
1332          };      {
1333        }        Iterator i = c.iterator();
1334      };        int pos = c.size();
1335    }        while (--pos >= 0)
1336            if (! equals(i.next(), element))
1337              return false;
1338          return true;
1339        }
1340    
1341        /**
1342         * The hash is just that of the element.
1343         */
1344        public int hashCode()
1345        {
1346          return hashCode(element);
1347        }
1348    
1349        /**
1350         * Returning an array is simple.
1351         */
1352        public Object[] toArray()
1353        {
1354          return new Object[] {element};
1355        }
1356    
1357        /**
1358         * Obvious string.
1359         */
1360        public String toString()
1361        {
1362          return "[" + element + "]";
1363        }
1364      } // class SingletonSet
1365    
1366    /**    /**
1367     * Obtain an immutable List consisting of a single element. The return value     * Obtain an immutable List consisting of a single element. The return value
1368     * of this method is Serializable.     * of this method is Serializable, and implements RandomAccess.
1369     *     *
1370     * @param o the single element.     * @param o the single element
1371     * @return an immutable List containing only o.     * @return an immutable List containing only o
1372       * @see Serializable
1373       * @see RandomAccess
1374       * @since 1.3
1375     */     */
1376    // It's not serializable because the spec is broken.    public static List singletonList(Object o)
   public static List singletonList(final Object o)  
1377    {    {
1378      return new AbstractList()      return new SingletonList(o);
1379      }
1380    
1381      /**
1382       * The implementation of {@link #singletonList(Object)}. This class name
1383       * is required for compatibility with Sun's JDK serializability.
1384       *
1385       * @author Eric Blake <ebb9@email.byu.edu>
1386       */
1387      private static final class SingletonList extends AbstractList
1388        implements Serializable, RandomAccess
1389      {
1390        /**
1391         * Compatible with JDK 1.4.
1392         */
1393        private static final long serialVersionUID = 3093736618740652951L;
1394    
1395        /**
1396         * The single element.
1397         * @serial the singleton
1398         */
1399        private final Object element;
1400    
1401        /**
1402         * Construct a singleton.
1403         * @param o the element
1404         */
1405        SingletonList(Object o)
1406        {
1407          element = o;
1408        }
1409    
1410        /**
1411         * The size: always 1!
1412         */
1413        public int size()
1414      {      {
1415        public int size()        return 1;
1416        {      }
         return 1;  
       }  
1417    
1418        public Object get(int index)      /**
1419        {       * Only index 0 is valid.
1420          if (index == 0)       */
1421            {      public Object get(int index)
1422              throw new IndexOutOfBoundsException();      {
1423            }        if (index == 0)
1424          else          return element;
1425            {        throw new IndexOutOfBoundsException();
1426              return o;      }
1427            }  
1428        }      // The remaining methods are optional, but provide a performance
1429      };      // advantage by not allocating unnecessary iterators in AbstractList.
1430    }      /**
1431         * The set only contains one element.
1432         */
1433        public boolean contains(Object o)
1434        {
1435          return equals(element, o);
1436        }
1437    
1438        /**
1439         * This is true if the other collection only contains the element.
1440         */
1441        public boolean containsAll(Collection c)
1442        {
1443          Iterator i = c.iterator();
1444          int pos = c.size();
1445          while (--pos >= 0)
1446            if (! equals(i.next(), element))
1447              return false;
1448          return true;
1449        }
1450    
1451        /**
1452         * Speed up the hashcode computation.
1453         */
1454        public int hashCode()
1455        {
1456          return 31 + hashCode(element);
1457        }
1458    
1459        /**
1460         * Either the list has it or not.
1461         */
1462        public int indexOf(Object o)
1463        {
1464          return equals(element, o) ? 0 : -1;
1465        }
1466    
1467        /**
1468         * Either the list has it or not.
1469         */
1470        public int lastIndexOf(Object o)
1471        {
1472          return equals(element, o) ? 0 : -1;
1473        }
1474    
1475        /**
1476         * Sublists are limited in scope.
1477         */
1478        public List subList(int from, int to)
1479        {
1480          if (from == to && (to == 0 || to == 1))
1481            return EMPTY_LIST;
1482          if (from == 0 && to == 1)
1483            return this;
1484          if (from > to)
1485            throw new IllegalArgumentException();
1486          throw new IndexOutOfBoundsException();
1487        }
1488    
1489        /**
1490         * Returning an array is simple.
1491         */
1492        public Object[] toArray()
1493        {
1494          return new Object[] {element};
1495        }
1496    
1497        /**
1498         * Obvious string.
1499         */
1500        public String toString()
1501        {
1502          return "[" + element + "]";
1503        }
1504      } // class SingletonList
1505    
1506    /**    /**
1507     * Obtain an immutable Map consisting of a single key value pair.     * Obtain an immutable Map consisting of a single key-value pair.
1508     * The return value of this method is Serializable.     * The return value of this method is Serializable.
1509     *     *
1510     * @param key the single key.     * @param key the single key
1511     * @param value the single value.     * @param value the single value
1512     * @return an immutable Map containing only the single key value pair.     * @return an immutable Map containing only the single key-value pair
1513       * @see Serializable
1514       * @since 1.3
1515     */     */
1516    // It's not serializable because the spec is broken.    public static Map singletonMap(Object key, Object value)
   public static Map singletonMap(final Object key, final Object value)  
1517    {    {
1518      return new AbstractMap()      return new SingletonMap(key, value);
     {  
       public Set entrySet()  
       {  
         return singleton(new BasicMapEntry(key, value));  
       }  
     };  
1519    }    }
1520    
1521    /**    /**
1522       * The implementation of {@link #singletonMap(Object)}. This class name
1523       * is required for compatibility with Sun's JDK serializability.
1524       *
1525       * @author Eric Blake <ebb9@email.byu.edu>
1526       */
1527      private static final class SingletonMap extends AbstractMap
1528        implements Serializable
1529      {
1530        /**
1531         * Compatible with JDK 1.4.
1532         */
1533        private static final long serialVersionUID = -6979724477215052911L;
1534    
1535        /**
1536         * The single key.
1537         * @serial the singleton key
1538         */
1539        private final Object k;
1540    
1541        /**
1542         * The corresponding value.
1543         * @serial the singleton value
1544         */
1545        private final Object v;
1546    
1547        /**
1548         * Cache the entry set.
1549         */
1550        private transient Set entries;
1551    
1552        /**
1553         * Construct a singleton.
1554         * @param key the key
1555         * @param value the value
1556         */
1557        SingletonMap(Object key, Object value)
1558        {
1559          k = key;
1560          v = value;
1561        }
1562    
1563        /**
1564         * There is a single immutable entry.
1565         */
1566        public Set entrySet()
1567        {
1568          if (entries == null)
1569            entries = singleton(new BasicMapEntry(k, v)
1570            {
1571              public Object setValue(Object o)
1572              {
1573                throw new UnsupportedOperationException();
1574              }
1575            });
1576          return entries;
1577        }
1578    
1579        // The remaining methods are optional, but provide a performance
1580        // advantage by not allocating unnecessary iterators in AbstractMap.
1581        /**
1582         * Single entry.
1583         */
1584        public boolean containsKey(Object key)
1585        {
1586          return equals(key, k);
1587        }
1588    
1589        /**
1590         * Single entry.
1591         */
1592        public boolean containsValue(Object value)
1593        {
1594          return equals(value, v);
1595        }
1596    
1597        /**
1598         * Single entry.
1599         */
1600        public Object get(Object key)
1601        {
1602          return equals(key, k) ? v : null;
1603        }
1604    
1605        /**
1606         * Calculate the hashcode directly.
1607         */
1608        public int hashCode()
1609        {
1610          return hashCode(k) ^ hashCode(v);
1611        }
1612    
1613        /**
1614         * Return the keyset.
1615         */
1616        public Set keySet()
1617        {
1618          if (keys == null)
1619            keys = singleton(k);
1620          return keys;
1621        }
1622    
1623        /**
1624         * The size: always 1!
1625         */
1626        public int size()
1627        {
1628          return 1;
1629        }
1630    
1631        /**
1632         * Return the values. Technically, a singleton, while more specific than
1633         * a general Collection, will work. Besides, that's what the JDK uses!
1634         */
1635        public Collection values()
1636        {
1637          if (values == null)
1638            values = singleton(v);
1639          return values;
1640        }
1641    
1642        /**
1643         * Obvious string.
1644         */
1645        public String toString()
1646        {
1647          return "{" + k + "=" + v + "}";
1648        }
1649      } // class SingletonMap
1650    
1651      /**
1652     * Sort a list according to the natural ordering of its elements. The list     * Sort a list according to the natural ordering of its elements. The list
1653     * must be modifiable, but can be of fixed size. The sort algorithm is     * must be modifiable, but can be of fixed size. The sort algorithm is
1654     * precisely that used by Arrays.sort(Object[]), which offers guaranteed     * precisely that used by Arrays.sort(Object[]), which offers guaranteed
# Line 700  public class Collections Line 1657  public class Collections
1657     * the array.     * the array.
1658     *     *
1659     * @param l the List to sort     * @param l the List to sort
1660     * @exception ClassCastException if some items are not mutually comparable     * @throws ClassCastException if some items are not mutually comparable
1661     * @exception UnsupportedOperationException if the List is not modifiable     * @throws UnsupportedOperationException if the List is not modifiable
1662       * @throws NullPointerException if some element is null
1663       * @see Arrays#sort(Object[])
1664     */     */
1665    public static void sort(List l)    public static void sort(List l)
1666    {    {
1667      Object[] a = l.toArray();      sort(l, null);
     Arrays.sort(a);  
     ListIterator i = l.listIterator();  
     for (int pos = 0; pos < a.length; pos++)  
       {  
         i.next();  
         i.set(a[pos]);  
       }  
1668    }    }
1669    
1670    /**    /**
# Line 724  public class Collections Line 1676  public class Collections
1676     * the array.     * the array.
1677     *     *
1678     * @param l the List to sort     * @param l the List to sort
1679     * @param c the Comparator specifying the ordering for the elements     * @param c the Comparator specifying the ordering for the elements, or
1680     * @exception ClassCastException if c will not compare some pair of items     *        null for natural ordering
1681     * @exception UnsupportedOperationException if the List is not modifiable     * @throws ClassCastException if c will not compare some pair of items
1682       * @throws UnsupportedOperationException if the List is not modifiable
1683       * @throws NullPointerException if null is compared by natural ordering
1684       *        (only possible when c is null)
1685       * @see Arrays#sort(Object[], Comparator)
1686     */     */
1687    public static void sort(List l, Comparator c)    public static void sort(List l, Comparator c)
1688    {    {
1689      Object[] a = l.toArray();      Object[] a = l.toArray();
1690      Arrays.sort(a, c);      Arrays.sort(a, c);
1691      ListIterator i = l.listIterator();      ListIterator i = l.listIterator(a.length);
1692      for (int pos = 0; pos < a.length; pos++)      for (int pos = a.length; --pos >= 0; )
1693        {        {
1694          i.next();          i.previous();
1695          i.set(a[pos]);          i.set(a[pos]);
1696        }        }
1697    }    }
1698    
1699    // All the methods from here on in require doc-comments.    /**
1700       * Swaps the elements at the specified positions within the list. Equal
1701       * positions have no effect.
1702       *
1703       * @param l the list to work on
1704       * @param i the first index to swap
1705       * @param j the second index
1706       * @throws UnsupportedOperationException if list.set is not supported
1707       * @throws IndexOutOfBoundsException if either i or j is &lt; 0 or &gt;=
1708       *         list.size()
1709       * @since 1.4
1710       */
1711      public static void swap(List l, int i, int j)
1712      {
1713        l.set(i, l.set(j, l.get(i)));
1714      }
1715    
1716    
1717      /**
1718       * Returns a synchronized (thread-safe) collection wrapper backed by the
1719       * given collection. Notice that element access through the iterators
1720       * is thread-safe, but if the collection can be structurally modified
1721       * (adding or removing elements) then you should synchronize around the
1722       * iteration to avoid non-deterministic behavior:<br>
1723       * <pre>
1724       * Collection c = Collections.synchronizedCollection(new Collection(...));
1725       * ...
1726       * synchronized (c)
1727       *   {
1728       *     Iterator i = c.iterator();
1729       *     while (i.hasNext())
1730       *       foo(i.next());
1731       *   }
1732       * </pre><p>
1733       *
1734       * Since the collection might be a List or a Set, and those have incompatible
1735       * equals and hashCode requirements, this relies on Object's implementation
1736       * rather than passing those calls on to the wrapped collection. The returned
1737       * Collection implements Serializable, but can only be serialized if
1738       * the collection it wraps is likewise Serializable.
1739       *
1740       * @param c the collection to wrap
1741       * @return a synchronized view of the collection
1742       * @see Serializable
1743       */
1744    public static Collection synchronizedCollection(Collection c)    public static Collection synchronizedCollection(Collection c)
1745    {    {
1746      return new SynchronizedCollection(c);      return new SynchronizedCollection(c);
1747    }    }
   public static List synchronizedList(List l)  
   {  
     return new SynchronizedList(l);  
   }  
   public static Map synchronizedMap(Map m)  
   {  
     return new SynchronizedMap(m);  
   }  
   public static Set synchronizedSet(Set s)  
   {  
     return new SynchronizedSet(s);  
   }  
   public static SortedMap synchronizedSortedMap(SortedMap m)  
   {  
     return new SynchronizedSortedMap(m);  
   }  
   public static SortedSet synchronizedSortedSet(SortedSet s)  
   {  
     return new SynchronizedSortedSet(s);  
   }  
   public static Collection unmodifiableCollection(Collection c)  
   {  
     return new UnmodifiableCollection(c);  
   }  
   public static List unmodifiableList(List l)  
   {  
     return new UnmodifiableList(l);  
   }  
   public static Map unmodifiableMap(Map m)  
   {  
     return new UnmodifiableMap(m);  
   }  
   public static Set unmodifiableSet(Set s)  
   {  
     return new UnmodifiableSet(s);  
   }  
   public static SortedMap unmodifiableSortedMap(SortedMap m)  
   {  
     return new UnmodifiableSortedMap(m);  
   }  
   public static SortedSet unmodifiableSortedSet(SortedSet s)  
   {  
     return new UnmodifiableSortedSet(s);  
   }  
   
   // Sun's spec will need to be checked for the precise names of these  
   // classes, for serializability's sake. However, from what I understand,  
   // serialization is broken for these classes anyway.  
   
   // Note: although this code is largely uncommented, it is all very  
   // mechanical and there's nothing really worth commenting.  
   // When serialization of these classes works, we'll need doc-comments on  
   // them to document the serialized form.  
   
   private static class UnmodifiableIterator implements Iterator  
   {  
     private Iterator i;  
1748    
1749      public UnmodifiableIterator(Iterator i)    /**
1750      {     * The implementation of {@link #synchronizedCollection(Collection)}. This
1751        this.i = i;     * class name is required for compatibility with Sun's JDK serializability.
1752      }     * Package visible, so that collections such as the one for
1753       * Hashtable.values() can specify which object to synchronize on.
1754      public Object next()     *
1755      {     * @author Eric Blake <ebb9@email.byu.edu>
1756        return i.next();     */
1757      }    static class SynchronizedCollection
1758      public boolean hasNext()      implements Collection, Serializable
     {  
       return i.hasNext();  
     }  
     public void remove()  
     {  
       throw new UnsupportedOperationException();  
     }  
   }  
   
   private static class UnmodifiableListIterator extends UnmodifiableIterator  
     implements ListIterator  
1759    {    {
1760      // This is stored both here and in the superclass, to avoid excessive      /**
1761      // casting.       * Compatible with JDK 1.4.
1762      private ListIterator li;       */
1763        private static final long serialVersionUID = 3053995032091335093L;
1764      public UnmodifiableListIterator(ListIterator li)  
1765      {      /**
1766        super(li);       * The wrapped collection. Package visible for use by subclasses.
1767        this.li = li;       * @serial the real collection
1768      }       */
1769        final Collection c;
1770      public boolean hasPrevious()  
1771      {      /**
1772        return li.hasPrevious();       * The object to synchronize on.  When an instance is created via public
1773      }       * methods, it will be this; but other uses like SynchronizedMap.values()
1774      public Object previous()       * must specify another mutex. Package visible for use by subclasses.
1775      {       * @serial the lock
1776        return li.previous();       */
1777      }      final Object mutex;
1778      public int nextIndex()  
1779      {      /**
1780        return li.nextIndex();       * Wrap a given collection.
1781      }       * @param c the collection to wrap
1782      public int previousIndex()       * @throws NullPointerException if c is null
1783      {       */
1784        return li.previousIndex();      SynchronizedCollection(Collection c)
     }  
     public void add(Object o)  
     {  
       throw new UnsupportedOperationException();  
     }  
     public void set(Object o)  
1785      {      {
1786        throw new UnsupportedOperationException();        this.c = c;
1787          mutex = this;
1788          if (c == null)
1789            throw new NullPointerException();
1790      }      }
   }  
1791    
1792    private static class UnmodifiableCollection implements Collection,      /**
1793      Serializable       * Called only by trusted code to specify the mutex as well as the
1794    {       * collection.
1795      Collection c;       * @param sync the mutex
1796         * @param c the collection
1797      public UnmodifiableCollection(Collection c)       */
1798        SynchronizedCollection(Object sync, Collection c)
1799      {      {
1800        this.c = c;        this.c = c;
1801          mutex = sync;
1802      }      }
1803    
1804      public boolean add(Object o)      public boolean add(Object o)
1805      {      {
1806        throw new UnsupportedOperationException();        synchronized (mutex)
1807            {
1808              return c.add(o);
1809            }
1810      }      }
1811      public boolean addAll(Collection c)  
1812        public boolean addAll(Collection col)
1813      {      {
1814        throw new UnsupportedOperationException();        synchronized (mutex)
1815            {
1816              return c.addAll(col);
1817            }
1818      }      }
1819    
1820      public void clear()      public void clear()
1821      {      {
1822        throw new UnsupportedOperationException();        synchronized (mutex)
1823            {
1824              c.clear();
1825            }
1826      }      }
1827    
1828      public boolean contains(Object o)      public boolean contains(Object o)
1829      {      {
1830        return c.contains(o);        synchronized (mutex)
1831            {
1832              return c.contains(o);
1833            }
1834      }      }
1835    
1836      public boolean containsAll(Collection c1)      public boolean containsAll(Collection c1)
1837      {      {
1838        return c.containsAll(c1);        synchronized (mutex)
1839            {
1840              return c.containsAll(c1);
1841            }
1842      }      }
1843    
1844      public boolean isEmpty()      public boolean isEmpty()
1845      {      {
1846        return c.isEmpty();        synchronized (mutex)
1847            {
1848              return c.isEmpty();
1849            }
1850      }      }
1851    
1852      public Iterator iterator()      public Iterator iterator()
1853      {      {
1854        return new UnmodifiableIterator(c.iterator());        synchronized (mutex)
1855            {
1856              return new SynchronizedIterator(mutex, c.iterator());
1857            }
1858      }      }
1859    
1860      public boolean remove(Object o)      public boolean remove(Object o)
1861      {      {
1862        throw new UnsupportedOperationException();        synchronized (mutex)
1863            {
1864              return c.remove(o);
1865            }
1866      }      }
1867      public boolean removeAll(Collection c)  
1868        public boolean removeAll(Collection col)
1869      {      {
1870        throw new UnsupportedOperationException();        synchronized (mutex)
1871            {
1872              return c.removeAll(col);
1873            }
1874      }      }
1875      public boolean retainAll(Collection c)  
1876        public boolean retainAll(Collection col)
1877      {      {
1878        throw new UnsupportedOperationException();        synchronized (mutex)
1879            {
1880              return c.retainAll(col);
1881            }
1882      }      }
1883    
1884      public int size()      public int size()
1885      {      {
1886        return c.size();        synchronized (mutex)
1887            {
1888              return c.size();
1889            }
1890      }      }
1891    
1892      public Object[] toArray()      public Object[] toArray()
1893      {      {
1894        return c.toArray();        synchronized (mutex)
1895            {
1896              return c.toArray();
1897            }
1898      }      }
1899      public Object[] toArray(Object[]a)  
1900      {      public Object[] toArray(Object[] a)
1901        return c.toArray(a);      {
1902          synchronized (mutex)
1903            {
1904              return c.toArray(a);
1905            }
1906      }      }
1907    
1908      public String toString()      public String toString()
1909      {      {
1910        return c.toString();        synchronized (mutex)
1911            {
1912              return c.toString();
1913            }
1914        }
1915      } // class SynchronizedCollection
1916    
1917      /**
1918       * The implementation of the various iterator methods in the
1919       * synchronized classes. These iterators must "sync" on the same object
1920       * as the collection they iterate over.
1921       *
1922       * @author Eric Blake <ebb9@email.byu.edu>
1923       */
1924      private static class SynchronizedIterator implements Iterator
1925      {
1926        /**
1927         * The object to synchronize on. Package visible for use by subclass.
1928         */
1929        final Object mutex;
1930    
1931        /**
1932         * The wrapped iterator.
1933         */
1934        private final Iterator i;
1935    
1936        /**
1937         * Only trusted code creates a wrapper, with the specified sync.
1938         * @param sync the mutex
1939         * @param i the wrapped iterator
1940         */
1941        SynchronizedIterator(Object sync, Iterator i)
1942        {
1943          this.i = i;
1944          mutex = sync;
1945        }
1946    
1947        public Object next()
1948        {
1949          synchronized (mutex)
1950            {
1951              return i.next();
1952            }
1953      }      }
1954    
1955        public boolean hasNext()
1956        {
1957          synchronized (mutex)
1958            {
1959              return i.hasNext();
1960            }
1961        }
1962    
1963        public void remove()
1964        {
1965          synchronized (mutex)
1966            {
1967              i.remove();
1968            }
1969        }
1970      } // class SynchronizedIterator
1971    
1972      /**
1973       * Returns a synchronized (thread-safe) list wrapper backed by the
1974       * given list. Notice that element access through the iterators
1975       * is thread-safe, but if the list can be structurally modified
1976       * (adding or removing elements) then you should synchronize around the
1977       * iteration to avoid non-deterministic behavior:<br>
1978       * <pre>
1979       * List l = Collections.synchronizedList(new List(...));
1980       * ...
1981       * synchronized (l)
1982       *   {
1983       *     Iterator i = l.iterator();
1984       *     while (i.hasNext())
1985       *       foo(i.next());
1986       *   }
1987       * </pre><p>
1988       *
1989       * The returned List implements Serializable, but can only be serialized if
1990       * the list it wraps is likewise Serializable. In addition, if the wrapped
1991       * list implements RandomAccess, this does too.
1992       *
1993       * @param l the list to wrap
1994       * @return a synchronized view of the list
1995       * @see Serializable
1996       * @see RandomAccess
1997       */
1998      public static List synchronizedList(List l)
1999      {
2000        if (l instanceof RandomAccess)
2001          return new SynchronizedRandomAccessList(l);
2002        return new SynchronizedList(l);
2003    }    }
2004    
2005    private static class UnmodifiableList extends UnmodifiableCollection    /**
2006       * The implementation of {@link #synchronizedList(List)} for sequential
2007       * lists. This class name is required for compatibility with Sun's JDK
2008       * serializability.
2009       *
2010       * @author Eric Blake <ebb9@email.byu.edu>
2011       */
2012      private static class SynchronizedList extends SynchronizedCollection
2013      implements List      implements List
2014    {    {
2015      // This is stored both here and in the superclass, to avoid excessive      /**
2016      // casting.       * Compatible with JDK 1.4.
2017      List l;       */
2018        private static final long serialVersionUID = -7754090372962971524L;
2019      public UnmodifiableList(List l)  
2020        /**
2021         * The wrapped list; stored both here and in the superclass to avoid
2022         * excessive casting. Package visible for use by subclass.
2023         * @serial the wrapped list
2024         */
2025        final List list;
2026    
2027        /**
2028         * Wrap a given list.
2029         * @param l the list to wrap
2030         * @throws NullPointerException if l is null
2031         */
2032        SynchronizedList(List l)
2033      {      {
2034        super(l);        super(l);
2035        this.l = l;        list = l;
2036        }
2037    
2038        /**
2039         * Called only by trusted code to specify the mutex as well as the list.
2040         * @param sync the mutex
2041         * @param l the list
2042         */
2043        SynchronizedList(Object sync, List l)
2044        {
2045          super(sync, l);
2046          list = l;
2047      }      }
2048    
2049      public void add(int index, Object o)      public void add(int index, Object o)
2050      {      {
2051        throw new UnsupportedOperationException();        synchronized (mutex)
2052            {
2053              list.add(index, o);
2054            }
2055      }      }
2056    
2057      public boolean addAll(int index, Collection c)      public boolean addAll(int index, Collection c)
2058      {      {
2059        throw new UnsupportedOperationException();        synchronized (mutex)
2060            {
2061              return list.addAll(index, c);
2062            }
2063      }      }
2064    
2065      public boolean equals(Object o)      public boolean equals(Object o)
2066      {      {
2067        return l.equals(o);        synchronized (mutex)
2068            {
2069              return list.equals(o);
2070            }
2071      }      }
2072    
2073      public Object get(int index)      public Object get(int index)
2074      {      {
2075        return l.get(index);        synchronized (mutex)
2076            {
2077              return list.get(index);
2078            }
2079      }      }
2080    
2081      public int hashCode()      public int hashCode()
2082      {      {
2083        return l.hashCode();        synchronized (mutex)
2084            {
2085              return list.hashCode();
2086            }
2087      }      }
2088    
2089      public int indexOf(Object o)      public int indexOf(Object o)
2090      {      {
2091        return l.indexOf(o);        synchronized (mutex)
2092            {
2093              return list.indexOf(o);
2094            }
2095      }      }
2096    
2097      public int lastIndexOf(Object o)      public int lastIndexOf(Object o)
2098      {      {
2099        return l.lastIndexOf(o);        synchronized (mutex)
2100            {
2101              return list.lastIndexOf(o);
2102            }
2103      }      }
2104    
2105      public ListIterator listIterator()      public ListIterator listIterator()
2106      {      {
2107        return new UnmodifiableListIterator(l.listIterator());        synchronized (mutex)
2108            {
2109              return new SynchronizedListIterator(mutex, list.listIterator());
2110            }
2111      }      }
2112    
2113      public ListIterator listIterator(int index)      public ListIterator listIterator(int index)
2114      {      {
2115        return new UnmodifiableListIterator(l.listIterator(index));        synchronized (mutex)
2116            {
2117              return new SynchronizedListIterator(mutex, list.listIterator(index));
2118            }
2119      }      }
2120    
2121      public Object remove(int index)      public Object remove(int index)
2122      {      {
2123        throw new UnsupportedOperationException();        synchronized (mutex)
2124            {
2125              return list.remove(index);
2126            }
2127      }      }
2128    
2129      public Object set(int index, Object o)      public Object set(int index, Object o)
2130      {      {
2131        throw new UnsupportedOperationException();        synchronized (mutex)
2132            {
2133              return list.set(index, o);
2134            }
2135      }      }
2136    
2137      public List subList(int fromIndex, int toIndex)      public List subList(int fromIndex, int toIndex)
2138      {      {
2139        return new UnmodifiableList(l.subList(fromIndex, toIndex));        synchronized (mutex)
2140            {
2141              return new SynchronizedList(mutex, list.subList(fromIndex, toIndex));
2142            }
2143      }      }
2144    }    } // class SynchronizedList
2145    
2146    private static class UnmodifiableSet extends UnmodifiableCollection    /**
2147      implements Set     * The implementation of {@link #synchronizedList(List)} for random-access
2148       * lists. This class name is required for compatibility with Sun's JDK
2149       * serializability.
2150       *
2151       * @author Eric Blake <ebb9@email.byu.edu>
2152       */
2153      private static final class SynchronizedRandomAccessList
2154        extends SynchronizedList implements RandomAccess
2155    {    {
2156      public UnmodifiableSet(Set s)      /**
2157         * Compatible with JDK 1.4.
2158         */
2159        private static final long serialVersionUID = 1530674583602358482L;
2160    
2161        /**
2162         * Wrap a given list.
2163         * @param l the list to wrap
2164         * @throws NullPointerException if l is null
2165         */
2166        SynchronizedRandomAccessList(List l)
2167      {      {
2168        super(s);        super(l);
2169      }      }
2170      public boolean equals(Object o)  
2171        /**
2172         * Called only by trusted code to specify the mutex as well as the
2173         * collection.
2174         * @param sync the mutex
2175         * @param l the list
2176         */
2177        SynchronizedRandomAccessList(Object sync, List l)
2178      {      {
2179        return c.equals(o);        super(sync, l);
2180      }      }
2181      public int hashCode()  
2182        public List subList(int fromIndex, int toIndex)
2183      {      {
2184        return c.hashCode();        synchronized (mutex)
2185            {
2186              return new SynchronizedRandomAccessList(mutex,
2187                                                      list.subList(fromIndex,
2188                                                                   toIndex));
2189            }
2190      }      }
2191    }    } // class SynchronizedRandomAccessList
2192    
2193    private static class UnmodifiableSortedSet extends UnmodifiableSet    /**
2194      implements SortedSet     * The implementation of {@link SynchronizedList#listIterator()}. This
2195       * iterator must "sync" on the same object as the list it iterates over.
2196       *
2197       * @author Eric Blake <ebb9@email.byu.edu>
2198       */
2199      private static final class SynchronizedListIterator
2200        extends SynchronizedIterator implements ListIterator
2201    {    {
2202      // This is stored both here and in the superclass, to avoid excessive      /**
2203      // casting.       * The wrapped iterator, stored both here and in the superclass to
2204      private SortedSet ss;       * avoid excessive casting.
2205         */
2206      public UnmodifiableSortedSet(SortedSet ss)      private final ListIterator li;
2207    
2208        /**
2209         * Only trusted code creates a wrapper, with the specified sync.
2210         * @param sync the mutex
2211         * @param li the wrapped iterator
2212         */
2213        SynchronizedListIterator(Object sync, ListIterator li)
2214      {      {
2215        super(ss);        super(sync, li);
2216        this.ss = ss;        this.li = li;
2217      }      }
2218    
2219      public Comparator comparator()      public void add(Object o)
2220      {      {
2221        return ss.comparator();        synchronized (mutex)
2222            {
2223              li.add(o);
2224            }
2225      }      }
2226      public Object first()      public boolean hasPrevious()
2227      {      {
2228        return ss.first();        synchronized (mutex)
2229            {
2230              return li.hasPrevious();
2231            }
2232      }      }
2233      public Object last()  
2234        public int nextIndex()
2235      {      {
2236        return ss.last();        synchronized (mutex)
2237            {
2238              return li.nextIndex();
2239            }
2240      }      }
2241      public SortedSet headSet(Object toElement)  
2242        public Object previous()
2243      {      {
2244        return new UnmodifiableSortedSet(ss.headSet(toElement));        synchronized (mutex)
2245            {
2246              return li.previous();
2247            }
2248      }      }
2249      public SortedSet tailSet(Object fromElement)  
2250        public int previousIndex()
2251      {      {
2252        return new UnmodifiableSortedSet(ss.tailSet(fromElement));        synchronized (mutex)
2253            {
2254              return li.previousIndex();
2255            }
2256      }      }
2257      public SortedSet subSet(Object fromElement, Object toElement)  
2258        public void set(Object o)
2259      {      {
2260        return new UnmodifiableSortedSet(ss.subSet(fromElement, toElement));        synchronized (mutex)
2261      }          {
2262              li.set(o);
2263            }
2264        }
2265      } // class SynchronizedListIterator
2266    
2267      /**
2268       * Returns a synchronized (thread-safe) map wrapper backed by the given
2269       * map. Notice that element access through the collection views and their
2270       * iterators are thread-safe, but if the map can be structurally modified
2271       * (adding or removing elements) then you should synchronize around the
2272       * iteration to avoid non-deterministic behavior:<br>
2273       * <pre>
2274       * Map m = Collections.synchronizedMap(new Map(...));
2275       * ...
2276       * Set s = m.keySet(); // safe outside a synchronized block
2277       * synchronized (m) // synch on m, not s
2278       *   {
2279       *     Iterator i = s.iterator();
2280       *     while (i.hasNext())
2281       *       foo(i.next());
2282       *   }
2283       * </pre><p>
2284       *
2285       * The returned Map implements Serializable, but can only be serialized if
2286       * the map it wraps is likewise Serializable.
2287       *
2288       * @param m the map to wrap
2289       * @return a synchronized view of the map
2290       * @see Serializable
2291       */
2292      public static Map synchronizedMap(Map m)
2293      {
2294        return new SynchronizedMap(m);
2295    }    }
2296    
2297    private static class UnmodifiableMap implements Map, Serializable    /**
2298       * The implementation of {@link #synchronizedMap(Map)}. This
2299       * class name is required for compatibility with Sun's JDK serializability.
2300       *
2301       * @author Eric Blake <ebb9@email.byu.edu>
2302       */
2303      private static class SynchronizedMap implements Map, Serializable
2304    {    {
2305      Map m;      /**
2306         * Compatible with JDK 1.4.
2307         */
2308        private static final long serialVersionUID = 1978198479659022715L;
2309    
2310        /**
2311         * The wrapped map.
2312         * @serial the real map
2313         */
2314        private final Map m;
2315    
2316        /**
2317         * The object to synchronize on.  When an instance is created via public
2318         * methods, it will be this; but other uses like
2319         * SynchronizedSortedMap.subMap() must specify another mutex. Package
2320         * visible for use by subclass.
2321         * @serial the lock
2322         */
2323        final Object mutex;
2324    
2325        /**
2326         * Cache the entry set.
2327         */
2328        private transient Set entries;
2329    
2330        /**
2331         * Cache the key set.
2332         */
2333        private transient Set keys;
2334    
2335        /**
2336         * Cache the value collection.
2337         */
2338        private transient Collection values;
2339    
2340        /**
2341         * Wrap a given map.
2342         * @param m the map to wrap
2343         * @throws NullPointerException if m is null
2344         */
2345        SynchronizedMap(Map m)
2346        {
2347          this.m = m;
2348          mutex = this;
2349          if (m == null)
2350            throw new NullPointerException();
2351        }
2352    
2353      public UnmodifiableMap(Map m)      /**
2354         * Called only by trusted code to specify the mutex as well as the map.
2355         * @param sync the mutex
2356         * @param m the map
2357         */
2358        SynchronizedMap(Object sync, Map m)
2359      {      {
2360        this.m = m;        this.m = m;
2361          mutex = sync;
2362      }      }
2363    
2364      public void clear()      public void clear()
2365      {      {
2366        throw new UnsupportedOperationException();        synchronized (mutex)
2367            {
2368              m.clear();
2369            }
2370      }      }
2371    
2372      public boolean containsKey(Object key)      public boolean containsKey(Object key)
2373      {      {
2374        return m.containsKey(key);        synchronized (mutex)
2375            {
2376              return m.containsKey(key);
2377            }
2378      }      }
2379    
2380      public boolean containsValue(Object value)      public boolean containsValue(Object value)
2381      {      {
2382        return m.containsValue(value);        synchronized (mutex)
2383            {
2384              return m.containsValue(value);
2385            }
2386      }      }
2387    
2388      // This is one of the ickiest cases of nesting I've ever seen. It just      // This is one of the ickiest cases of nesting I've ever seen. It just
2389      // means "return an UnmodifiableSet, except that the iterator() method      // means "return a SynchronizedSet, except that the iterator() method
2390      // returns an UnmodifiableIterator whos next() method returns an      // returns an SynchronizedIterator whose next() method returns a
2391      // unmodifiable wrapper around its normal return value".      // synchronized wrapper around its normal return value".
2392      public Set entrySet()      public Set entrySet()
2393      {      {
2394        return new UnmodifiableSet(m.entrySet())        // Define this here to spare some nesting.
2395          class SynchronizedMapEntry implements Map.Entry
2396        {        {
2397          public Iterator iterator()          final Map.Entry e;
2398          {          SynchronizedMapEntry(Object o)
2399            return new UnmodifiableIterator(c.iterator())          {
2400            {            e = (Map.Entry) o;
2401              public Object next()          }
2402              {          public boolean equals(Object o)
2403                final Map.Entry e = (Map.Entry) super.next();          {
2404                return new Map.Entry()            synchronized (mutex)
2405                {              {
2406                  public Object getKey()                return e.equals(o);
2407                  {              }
2408                    return e.getKey();          }
2409                  }          public Object getKey()
2410                  public Object getValue()          {
2411                  {            synchronized (mutex)
2412                    return e.getValue();              {
2413                  }                return e.getKey();
2414                  public Object setValue(Object value)              }
2415                  {          }
2416                    throw new UnsupportedOperationException();          public Object getValue()
2417                  }          {
2418                  public int hashCode()            synchronized (mutex)
2419                  {              {
2420                    return e.hashCode();                return e.getValue();
2421                  }              }
2422                  public boolean equals(Object o)          }
2423                  {          public int hashCode()
2424                    return e.equals(o);          {
2425                  }            synchronized (mutex)
2426                };              {
2427              }                return e.hashCode();
2428            };              }
2429          }          }
2430        };          public Object setValue(Object value)
2431            {
2432              synchronized (mutex)
2433                {
2434                  return e.setValue(value);
2435                }
2436            }
2437            public String toString()
2438            {
2439              synchronized (mutex)
2440                {
2441                  return e.toString();
2442                }
2443            }
2444          } // class SynchronizedMapEntry
2445    
2446          // Now the actual code.
2447          if (entries == null)
2448            synchronized (mutex)
2449              {
2450                entries = new SynchronizedSet(mutex, m.entrySet())
2451                {
2452                  public Iterator iterator()
2453                  {
2454                    synchronized (super.mutex)
2455                      {
2456                        return new SynchronizedIterator(super.mutex, c.iterator())
2457                        {
2458                          public Object next()
2459                          {
2460                            synchronized (super.mutex)
2461                              {
2462                                return new SynchronizedMapEntry(super.next());
2463                              }
2464                          }
2465                        };
2466                      }
2467                  }
2468                };
2469              }
2470          return entries;
2471      }      }
2472    
2473      public boolean equals(Object o)      public boolean equals(Object o)
2474      {      {
2475        return m.equals(o);        synchronized (mutex)
2476            {
2477              return m.equals(o);
2478            }
2479      }      }
2480    
2481      public Object get(Object key)      public Object get(Object key)
2482      {      {
2483        return m.get(key);        synchronized (mutex)
2484      }          {
2485      public Object put(Object key, Object value)            return m.get(key);
2486      {          }
       throw new UnsupportedOperationException();  
2487      }      }
2488    
2489      public int hashCode()      public int hashCode()
2490      {      {
2491        return m.hashCode();        synchronized (mutex)
2492            {
2493              return m.hashCode();
2494            }
2495      }      }
2496    
2497      public boolean isEmpty()      public boolean isEmpty()
2498      {      {
2499        return m.isEmpty();        synchronized (mutex)
2500            {
2501              return m.isEmpty();
2502            }
2503      }      }
2504    
2505      public Set keySet()      public Set keySet()
2506      {      {
2507        return new UnmodifiableSet(m.keySet());        if (keys == null)
2508            synchronized (mutex)
2509              {
2510                keys = new SynchronizedSet(mutex, m.keySet());
2511              }
2512          return keys;
2513      }      }
2514      public void putAll(Map m)  
2515        public Object put(Object key, Object value)
2516      {      {
2517        throw new UnsupportedOperationException();        synchronized (mutex)
2518            {
2519              return m.put(key, value);
2520            }
2521        }
2522    
2523        public void putAll(Map map)
2524        {
2525          synchronized (mutex)
2526            {
2527              m.putAll(map);
2528            }
2529      }      }
2530    
2531      public Object remove(Object o)      public Object remove(Object o)
2532      {      {
2533        throw new UnsupportedOperationException();        synchronized (mutex)
2534            {
2535              return m.remove(o);
2536            }
2537      }      }
2538    
2539      public int size()      public int size()
2540      {      {
2541        return m.size();        synchronized (mutex)
2542            {
2543              return m.size();
2544            }
2545      }      }
2546    
2547        public String toString()
2548        {
2549          synchronized (mutex)
2550            {
2551              return m.toString();
2552            }
2553        }
2554    
2555      public Collection values()      public Collection values()
2556      {      {
2557        return new UnmodifiableCollection(m.values());        if (values == null)
2558            synchronized (mutex)
2559              {
2560                values = new SynchronizedCollection(mutex, m.values());
2561              }
2562          return values;
2563        }
2564      } // class SynchronizedMap
2565    
2566      /**
2567       * Returns a synchronized (thread-safe) set wrapper backed by the given
2568       * set. Notice that element access through the iterator is thread-safe, but
2569       * if the set can be structurally modified (adding or removing elements)
2570       * then you should synchronize around the iteration to avoid
2571       * non-deterministic behavior:<br>
2572       * <pre>
2573       * Set s = Collections.synchronizedSet(new Set(...));
2574       * ...
2575       * synchronized (s)
2576       *   {
2577       *     Iterator i = s.iterator();
2578       *     while (i.hasNext())
2579       *       foo(i.next());
2580       *   }
2581       * </pre><p>
2582       *
2583       * The returned Set implements Serializable, but can only be serialized if
2584       * the set it wraps is likewise Serializable.
2585       *
2586       * @param s the set to wrap
2587       * @return a synchronized view of the set
2588       * @see Serializable
2589       */
2590      public static Set synchronizedSet(Set s)
2591      {
2592        return new SynchronizedSet(s);
2593      }
2594    
2595      /**
2596       * The implementation of {@link #synchronizedSet(Set)}. This class
2597       * name is required for compatibility with Sun's JDK serializability.
2598       * Package visible, so that sets such as Hashtable.keySet()
2599       * can specify which object to synchronize on.
2600       *
2601       * @author Eric Blake <ebb9@email.byu.edu>
2602       */
2603      static class SynchronizedSet extends SynchronizedCollection
2604        implements Set
2605      {
2606        /**
2607         * Compatible with JDK 1.4.
2608         */
2609        private static final long serialVersionUID = 487447009682186044L;
2610    
2611        /**
2612         * Wrap a given set.
2613         * @param s the set to wrap
2614         * @throws NullPointerException if s is null
2615         */
2616        SynchronizedSet(Set s)
2617        {
2618          super(s);
2619        }
2620    
2621        /**
2622         * Called only by trusted code to specify the mutex as well as the set.
2623         * @param sync the mutex
2624         * @param s the set
2625         */
2626        SynchronizedSet(Object sync, Set s)
2627        {
2628          super(sync, s);
2629      }      }
2630      public String toString()  
2631        public boolean equals(Object o)
2632      {      {
2633        return m.toString();        synchronized (mutex)
2634            {
2635              return c.equals(o);
2636            }
2637      }      }
2638    
2639        public int hashCode()
2640        {
2641          synchronized (mutex)
2642            {
2643              return c.hashCode();
2644            }
2645        }
2646      } // class SynchronizedSet
2647    
2648      /**
2649       * Returns a synchronized (thread-safe) sorted map wrapper backed by the
2650       * given map. Notice that element access through the collection views,
2651       * subviews, and their iterators are thread-safe, but if the map can be
2652       * structurally modified (adding or removing elements) then you should
2653       * synchronize around the iteration to avoid non-deterministic behavior:<br>
2654       * <pre>
2655       * SortedMap m = Collections.synchronizedSortedMap(new SortedMap(...));
2656       * ...
2657       * Set s = m.keySet(); // safe outside a synchronized block
2658       * SortedMap m2 = m.headMap(foo); // safe outside a synchronized block
2659       * Set s2 = m2.keySet(); // safe outside a synchronized block
2660       * synchronized (m) // synch on m, not m2, s or s2
2661       *   {
2662       *     Iterator i = s.iterator();
2663       *     while (i.hasNext())
2664       *       foo(i.next());
2665       *     i = s2.iterator();
2666       *     while (i.hasNext())
2667       *       bar(i.next());
2668       *   }
2669       * </pre><p>
2670       *
2671       * The returned SortedMap implements Serializable, but can only be
2672       * serialized if the map it wraps is likewise Serializable.
2673       *
2674       * @param m the sorted map to wrap
2675       * @return a synchronized view of the sorted map
2676       * @see Serializable
2677       */
2678      public static SortedMap synchronizedSortedMap(SortedMap m)
2679      {
2680        return new SynchronizedSortedMap(m);
2681    }    }
2682    
2683    private static class UnmodifiableSortedMap extends UnmodifiableMap    /**
2684       * The implementation of {@link #synchronizedSortedMap(SortedMap)}. This
2685       * class name is required for compatibility with Sun's JDK serializability.
2686       *
2687       * @author Eric Blake <ebb9@email.byu.edu>
2688       */
2689      private static final class SynchronizedSortedMap extends SynchronizedMap
2690      implements SortedMap      implements SortedMap
2691    {    {
2692      // This is stored both here and in the superclass, to avoid excessive      /**
2693      // casting.       * Compatible with JDK 1.4.
2694      private SortedMap sm;       */
2695        private static final long serialVersionUID = -8798146769416483793L;
2696      public UnmodifiableSortedMap(SortedMap sm)  
2697        /**
2698         * The wrapped map; stored both here and in the superclass to avoid
2699         * excessive casting.
2700         * @serial the wrapped map
2701         */
2702        private final SortedMap sm;
2703    
2704        /**
2705         * Wrap a given map.
2706         * @param sm the map to wrap
2707         * @throws NullPointerException if sm is null
2708         */
2709        SynchronizedSortedMap(SortedMap sm)
2710      {      {
2711        super(sm);        super(sm);
2712        this.sm = sm;        this.sm = sm;
2713      }      }
2714    
2715      public Comparator comparator()      /**
2716         * Called only by trusted code to specify the mutex as well as the map.
2717         * @param sync the mutex
2718         * @param sm the map
2719         */
2720        SynchronizedSortedMap(Object sync, SortedMap sm)
2721      {      {
2722        return sm.comparator();        super(sync, sm);
2723          this.sm = sm;
2724      }      }
2725      public Object firstKey()  
2726        public Comparator comparator()
2727      {      {
2728        return sm.firstKey();        synchronized (mutex)
2729            {
2730              return sm.comparator();
2731            }
2732      }      }
2733      public Object lastKey()  
2734        public Object firstKey()
2735      {      {
2736        return sm.lastKey();        synchronized (mutex)
2737            {
2738              return sm.firstKey();
2739            }
2740      }      }
2741    
2742      public SortedMap headMap(Object toKey)      public SortedMap headMap(Object toKey)
2743      {      {
2744        return new UnmodifiableSortedMap(sm.headMap(toKey));        synchronized (mutex)
2745            {
2746              return new SynchronizedSortedMap(mutex, sm.headMap(toKey));
2747            }
2748      }      }
2749      public SortedMap tailMap(Object fromKey)  
2750        public Object lastKey()
2751      {      {
2752        return new UnmodifiableSortedMap(sm.tailMap(fromKey));        synchronized (mutex)
2753            {
2754              return sm.lastKey();
2755            }
2756      }      }
2757    
2758      public SortedMap subMap(Object fromKey, Object toKey)      public SortedMap subMap(Object fromKey, Object toKey)
2759      {      {
2760        return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));        synchronized (mutex)
2761            {
2762              return new SynchronizedSortedMap(mutex, sm.subMap(fromKey, toKey));
2763            }
2764      }      }
   }  
2765    
2766    // All the "Synchronized" wrapper objects include a "sync" field which      public SortedMap tailMap(Object fromKey)
2767    // specifies what object to synchronize on. That way, nested wrappers such as      {
2768    // UnmodifiableMap.keySet synchronize on the right things.        synchronized (mutex)
2769            {
2770    private static class SynchronizedIterator implements Iterator            return new SynchronizedSortedMap(mutex, sm.tailMap(fromKey));
2771            }
2772        }
2773      } // class SynchronizedSortedMap
2774    
2775      /**
2776       * Returns a synchronized (thread-safe) sorted set wrapper backed by the
2777       * given set. Notice that element access through the iterator and through
2778       * subviews are thread-safe, but if the set can be structurally modified
2779       * (adding or removing elements) then you should synchronize around the
2780       * iteration to avoid non-deterministic behavior:<br>
2781       * <pre>
2782       * SortedSet s = Collections.synchronizedSortedSet(new SortedSet(...));
2783       * ...
2784       * SortedSet s2 = s.headSet(foo); // safe outside a synchronized block
2785       * synchronized (s) // synch on s, not s2
2786       *   {
2787       *     Iterator i = s2.iterator();
2788       *     while (i.hasNext())
2789       *       foo(i.next());
2790       *   }
2791       * </pre><p>
2792       *
2793       * The returned SortedSet implements Serializable, but can only be
2794       * serialized if the set it wraps is likewise Serializable.
2795       *
2796       * @param s the sorted set to wrap
2797       * @return a synchronized view of the sorted set
2798       * @see Serializable
2799       */
2800      public static SortedSet synchronizedSortedSet(SortedSet s)
2801    {    {
2802      Object sync;      return new SynchronizedSortedSet(s);
2803      private Iterator i;    }
2804    
2805      public SynchronizedIterator(Object sync, Iterator i)    /**
2806       * The implementation of {@link #synchronizedSortedSet(SortedSet)}. This
2807       * class name is required for compatibility with Sun's JDK serializability.
2808       *
2809       * @author Eric Blake <ebb9@email.byu.edu>
2810       */
2811      private static final class SynchronizedSortedSet extends SynchronizedSet
2812        implements SortedSet
2813      {
2814        /**
2815         * Compatible with JDK 1.4.
2816         */
2817        private static final long serialVersionUID = 8695801310862127406L;
2818    
2819        /**
2820         * The wrapped set; stored both here and in the superclass to avoid
2821         * excessive casting.
2822         * @serial the wrapped set
2823         */
2824        private final SortedSet ss;
2825    
2826        /**
2827         * Wrap a given set.
2828         * @param ss the set to wrap
2829         * @throws NullPointerException if ss is null
2830         */
2831        SynchronizedSortedSet(SortedSet ss)
2832      {      {
2833        this.sync = sync;        super(ss);
2834        this.i = i;        this.ss = ss;
2835      }      }
2836    
2837      public Object next()      /**
2838         * Called only by trusted code to specify the mutex as well as the set.
2839         * @param sync the mutex
2840         * @param l the list
2841         */
2842        SynchronizedSortedSet(Object sync, SortedSet ss)
2843      {      {
2844        synchronized(sync)        super(sync, ss);
2845        {        this.ss = ss;
         return i.next();  
       }  
     }  
     public boolean hasNext()  
     {  
       synchronized(sync)  
       {  
         return i.hasNext();  
       }  
     }  
     public void remove()  
     {  
       synchronized(sync)  
       {  
         i.remove();  
       }  
2846      }      }
   }  
   
   private static class SynchronizedListIterator extends SynchronizedIterator  
     implements ListIterator  
   {  
     // This is stored both here and in the superclass, to avoid excessive  
     // casting.  
     private ListIterator li;  
2847    
2848      public SynchronizedListIterator(Object sync, ListIterator li)      public Comparator comparator()
2849      {      {
2850        super(sync, li);        synchronized (mutex)
2851        this.li = li;          {
2852              return ss.comparator();
2853            }
2854      }      }
2855    
2856      public boolean hasPrevious()      public Object first()
2857      {      {
2858        synchronized(sync)        synchronized (mutex)
2859        {          {
2860          return li.hasPrevious();            return ss.first();
2861        }          }
2862      }      }
2863      public Object previous()  
2864        public SortedSet headSet(Object toElement)
2865      {      {
2866        synchronized(sync)        synchronized (mutex)
2867        {          {
2868          return li.previous();            return new SynchronizedSortedSet(mutex, ss.headSet(toElement));
2869        }          }
2870      }      }
2871      public int nextIndex()  
2872      {      public Object last()
       synchronized(sync)  
       {  
         return li.nextIndex();  
       }  
     }  
     public int previousIndex()  
2873      {      {
2874        synchronized(sync)        synchronized (mutex)
2875        {          {
2876          return li.previousIndex();            return ss.last();
2877        }          }
2878      }      }
2879      public void add(Object o)  
2880        public SortedSet subSet(Object fromElement, Object toElement)
2881      {      {
2882        synchronized(sync)        synchronized (mutex)
2883        {          {
2884          li.add(o);            return new SynchronizedSortedSet(mutex,
2885        }                                             ss.subSet(fromElement, toElement));
2886            }
2887      }      }
2888      public void set(Object o)  
2889        public SortedSet tailSet(Object fromElement)
2890      {      {
2891        synchronized(sync)        synchronized (mutex)
2892        {          {
2893          li.set(o);            return new SynchronizedSortedSet(mutex, ss.tailSet(fromElement));
2894        }          }
2895      }      }
2896      } // class SynchronizedSortedSet
2897    
2898    
2899      /**
2900       * Returns an unmodifiable view of the given collection. This allows
2901       * "read-only" access, although changes in the backing collection show up
2902       * in this view. Attempts to modify the collection directly or via iterators
2903       * will fail with {@link UnsupportedOperationException}.
2904       * <p>
2905       *
2906       * Since the collection might be a List or a Set, and those have incompatible
2907       * equals and hashCode requirements, this relies on Object's implementation
2908       * rather than passing those calls on to the wrapped collection. The returned
2909       * Collection implements Serializable, but can only be serialized if
2910       * the collection it wraps is likewise Serializable.
2911       *
2912       * @param c the collection to wrap
2913       * @return a read-only view of the collection
2914       * @see Serializable
2915       */
2916      public static Collection unmodifiableCollection(Collection c)
2917      {
2918        return new UnmodifiableCollection(c);
2919    }    }
2920    
2921    /**    /**
2922     * Package visible, so that collections such as the one for     * The implementation of {@link #unmodifiableCollection(Collection)}. This
2923     * Hashtable.values() can specify which object to synchronize on.     * class name is required for compatibility with Sun's JDK serializability.
2924       *
2925       * @author Eric Blake <ebb9@email.byu.edu>
2926     */     */
2927    static class SynchronizedCollection implements Collection,    private static class UnmodifiableCollection
2928      Serializable      implements Collection, Serializable
2929    {    {
2930      Object sync;      /**
2931      Collection c;       * Compatible with JDK 1.4.
2932         */
2933      public SynchronizedCollection(Collection c)      private static final long serialVersionUID = 1820017752578914078L;
2934    
2935        /**
2936         * The wrapped collection. Package visible for use by subclasses.
2937         * @serial the real collection
2938         */
2939        final Collection c;
2940    
2941        /**
2942         * Wrap a given collection.
2943         * @param c the collection to wrap
2944         * @throws NullPointerException if c is null
2945         */
2946        UnmodifiableCollection(Collection c)
2947      {      {
       this.sync = this;  
2948        this.c = c;        this.c = c;
2949      }        if (c == null)
2950      public SynchronizedCollection(Object sync, Collection c)          throw new NullPointerException();
     {  
       this.c = c;  
       this.sync = sync;  
2951      }      }
2952    
2953      public boolean add(Object o)      public boolean add(Object o)
2954      {      {
2955        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return c.add(o);  
       }  
2956      }      }
2957      public boolean addAll(Collection col)  
2958        public boolean addAll(Collection c)
2959      {      {
2960        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return c.addAll(col);  
       }  
2961      }      }
2962    
2963      public void clear()      public void clear()
2964      {      {
2965        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         c.clear();  
       }  
2966      }      }
2967    
2968      public boolean contains(Object o)      public boolean contains(Object o)
2969      {      {
2970        synchronized(sync)        return c.contains(o);
       {  
         return c.contains(o);  
       }  
2971      }      }
2972    
2973      public boolean containsAll(Collection c1)      public boolean containsAll(Collection c1)
2974      {      {
2975        synchronized(sync)        return c.containsAll(c1);
       {  
         return c.containsAll(c1);  
       }  
2976      }      }
2977    
2978      public boolean isEmpty()      public boolean isEmpty()
2979      {      {
2980        synchronized(sync)        return c.isEmpty();
       {  
         return c.isEmpty();  
       }  
2981      }      }
2982    
2983      public Iterator iterator()      public Iterator iterator()
2984      {      {
2985        synchronized(sync)        return new UnmodifiableIterator(c.iterator());
       {  
         return new SynchronizedIterator(sync, c.iterator());  
       }  
2986      }      }
2987    
2988      public boolean remove(Object o)      public boolean remove(Object o)
2989      {      {
2990        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return c.remove(o);  
       }  
2991      }      }
2992      public boolean removeAll(Collection col)  
2993        public boolean removeAll(Collection c)
2994      {      {
2995        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return c.removeAll(col);  
       }  
2996      }      }
2997      public boolean retainAll(Collection col)  
2998        public boolean retainAll(Collection c)
2999      {      {
3000        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return c.retainAll(col);  
       }  
3001      }      }
3002    
3003      public int size()      public int size()
3004      {      {
3005        synchronized(sync)        return c.size();
       {  
         return c.size();  
       }  
3006      }      }
3007    
3008      public Object[] toArray()      public Object[] toArray()
3009      {      {
3010        synchronized(sync)        return c.toArray();
       {  
         return c.toArray();  
       }  
3011      }      }
3012      public Object[] toArray(Object[]a)  
3013        public Object[] toArray(Object[] a)
3014      {      {
3015        synchronized(sync)        return c.toArray(a);
       {  
         return c.toArray(a);  
       }  
3016      }      }
3017    
3018      public String toString()      public String toString()
3019      {      {
3020        synchronized(sync)        return c.toString();
       {  
         return c.toString();  
       }  
3021      }      }
3022    }    } // class UnmodifiableCollection
3023    
3024    private static class SynchronizedList extends SynchronizedCollection    /**
3025      implements List     * The implementation of the various iterator methods in the
3026       * unmodifiable classes.
3027       *
3028       * @author Eric Blake <ebb9@email.byu.edu>
3029       */
3030      private static class UnmodifiableIterator implements Iterator
3031    {    {
3032      // This is stored both here and in the superclass, to avoid excessive      /**
3033      // casting.       * The wrapped iterator.
3034      List l;       */
3035        private final Iterator i;
3036    
3037        /**
3038         * Only trusted code creates a wrapper.
3039         * @param i the wrapped iterator
3040         */
3041        UnmodifiableIterator(Iterator i)
3042        {
3043          this.i = i;
3044        }
3045    
3046      public SynchronizedList(Object sync, List l)      public Object next()
3047      {      {
3048        super(sync, l);        return i.next();
3049        this.l = l;      }
3050    
3051        public boolean hasNext()
3052        {
3053          return i.hasNext();
3054      }      }
3055      public SynchronizedList(List l)  
3056        public void remove()
3057        {
3058          throw new UnsupportedOperationException();
3059        }
3060      } // class UnmodifiableIterator
3061    
3062      /**
3063       * Returns an unmodifiable view of the given list. This allows
3064       * "read-only" access, although changes in the backing list show up
3065       * in this view. Attempts to modify the list directly, via iterators, or
3066       * via sublists, will fail with {@link UnsupportedOperationException}.
3067       * <p>
3068       *
3069       * The returned List implements Serializable, but can only be serialized if
3070       * the list it wraps is likewise Serializable. In addition, if the wrapped
3071       * list implements RandomAccess, this does too.
3072       *
3073       * @param l the list to wrap
3074       * @return a read-only view of the list
3075       * @see Serializable
3076       * @see RandomAccess
3077       */
3078      public static List unmodifiableList(List l)
3079      {
3080        if (l instanceof RandomAccess)
3081          return new UnmodifiableRandomAccessList(l);
3082        return new UnmodifiableList(l);
3083      }
3084    
3085      /**
3086       * The implementation of {@link #unmodifiableList(List)} for sequential
3087       * lists. This class name is required for compatibility with Sun's JDK
3088       * serializability.
3089       *
3090       * @author Eric Blake <ebb9@email.byu.edu>
3091       */
3092      private static class UnmodifiableList extends UnmodifiableCollection
3093        implements List
3094      {
3095        /**
3096         * Compatible with JDK 1.4.
3097         */
3098        private static final long serialVersionUID = -283967356065247728L;
3099    
3100    
3101        /**
3102         * The wrapped list; stored both here and in the superclass to avoid
3103         * excessive casting. Package visible for use by subclass.
3104         * @serial the wrapped list
3105         */
3106        final List list;
3107    
3108        /**
3109         * Wrap a given list.
3110         * @param l the list to wrap
3111         * @throws NullPointerException if l is null
3112         */
3113        UnmodifiableList(List l)
3114      {      {
3115        super(l);        super(l);
3116        this.l = l;        list = l;
3117      }      }
3118    
3119      public void add(int index, Object o)      public void add(int index, Object o)
3120      {      {
3121        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         l.add(index, o);  
       }  
3122      }      }
3123    
3124      public boolean addAll(int index, Collection c)      public boolean addAll(int index, Collection c)
3125      {      {
3126        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return l.addAll(index, c);  
       }  
3127      }      }
3128    
3129      public boolean equals(Object o)      public boolean equals(Object o)
3130      {      {
3131        synchronized(sync)        return list.equals(o);
       {  
         return l.equals(o);  
       }  
3132      }      }
3133    
3134      public Object get(int index)      public Object get(int index)
3135      {      {
3136        synchronized(sync)        return list.get(index);
       {  
         return l.get(index);  
       }  
3137      }      }
3138    
3139      public int hashCode()      public int hashCode()
3140      {      {
3141        synchronized(sync)        return list.hashCode();
       {  
         return l.hashCode();  
       }  
3142      }      }
3143    
3144      public int indexOf(Object o)      public int indexOf(Object o)
3145      {      {
3146        synchronized(sync)        return list.indexOf(o);
       {  
         return l.indexOf(o);  
       }  
3147      }      }
3148    
3149      public int lastIndexOf(Object o)      public int lastIndexOf(Object o)
3150      {      {
3151        synchronized(sync)        return list.lastIndexOf(o);
       {  
         return l.lastIndexOf(o);  
       }  
3152      }      }
3153    
3154      public ListIterator listIterator()      public ListIterator listIterator()
3155      {      {
3156        synchronized(sync)        return new UnmodifiableListIterator(list.listIterator());
       {  
         return new SynchronizedListIterator(sync, l.listIterator());  
       }  
3157      }      }
3158    
3159      public ListIterator listIterator(int index)      public ListIterator listIterator(int index)
3160      {      {
3161        synchronized(sync)        return new UnmodifiableListIterator(list.listIterator(index));
       {  
         return new SynchronizedListIterator(sync, l.listIterator(index));  
       }  
3162      }      }
3163    
3164      public Object remove(int index)      public Object remove(int index)
3165      {      {
3166        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return l.remove(index);  
       }  
     }  
     public boolean remove(Object o)  
     {  
       synchronized(sync)  
       {  
         return l.remove(o);  
       }  
3167      }      }
3168    
3169      public Object set(int index, Object o)      public Object set(int index, Object o)
3170      {      {
3171        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return l.set(index, o);  
       }  
3172      }      }
3173    
3174      public List subList(int fromIndex, int toIndex)      public List subList(int fromIndex, int toIndex)
3175      {      {
3176        synchronized(sync)        return unmodifiableList(list.subList(fromIndex, toIndex));
       {  
         return new SynchronizedList(l.subList(fromIndex, toIndex));  
       }  
3177      }      }
3178    }    } // class UnmodifiableList
3179    
3180    /**    /**
3181     * Package visible, so that sets such as the one for Hashtable.keySet()     * The implementation of {@link #unmodifiableList(List)} for random-access
3182     * can specify which object to synchronize on.     * lists. This class name is required for compatibility with Sun's JDK
3183       * serializability.
3184       *
3185       * @author Eric Blake <ebb9@email.byu.edu>
3186     */     */
3187    static class SynchronizedSet extends SynchronizedCollection    private static final class UnmodifiableRandomAccessList
3188      implements Set      extends UnmodifiableList implements RandomAccess
3189    {    {
3190      public SynchronizedSet(Object sync, Set s)      /**
3191      {       * Compatible with JDK 1.4.
3192        super(sync, s);       */
3193      }      private static final long serialVersionUID = -2542308836966382001L;
3194      public SynchronizedSet(Set s)  
3195      {      /**
3196        super(s);       * Wrap a given list.
3197      }       * @param l the list to wrap
3198         * @throws NullPointerException if l is null
3199      public boolean equals(Object o)       */
3200      {      UnmodifiableRandomAccessList(List l)
       synchronized(sync)  
       {  
         return c.equals(o);  
       }  
     }  
     public int hashCode()  
3201      {      {
3202        synchronized(sync)        super(l);
       {  
         return c.hashCode();  
       }  
3203      }      }
3204    }    } // class UnmodifiableRandomAccessList
3205    
3206    private static class SynchronizedSortedSet extends SynchronizedSet    /**
3207      implements SortedSet     * The implementation of {@link UnmodifiableList#listIterator()}.
3208       *
3209       * @author Eric Blake <ebb9@email.byu.edu>
3210       */
3211      private static final class UnmodifiableListIterator
3212        extends UnmodifiableIterator implements ListIterator
3213    {    {
3214      // This is stored both here and in the superclass, to avoid excessive      /**
3215      // casting.       * The wrapped iterator, stored both here and in the superclass to
3216      private SortedSet ss;       * avoid excessive casting.
3217         */
3218      public SynchronizedSortedSet(Object sync, SortedSet ss)      private final ListIterator li;
3219      {  
3220        super(sync, ss);      /**
3221        this.ss = ss;       * Only trusted code creates a wrapper.
3222      }       * @param li the wrapped iterator
3223      public SynchronizedSortedSet(SortedSet ss)       */
3224        UnmodifiableListIterator(ListIterator li)
3225      {      {
3226        super(ss);        super(li);
3227        this.ss = ss;        this.li = li;
3228      }      }
3229    
3230      public Comparator comparator()      public void add(Object o)
3231      {      {
3232        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return ss.comparator();  
       }  
3233      }      }
3234      public Object first()  
3235        public boolean hasPrevious()
3236      {      {
3237        synchronized(sync)        return li.hasPrevious();
       {  
         return ss.first();  
       }  
3238      }      }
3239      public Object last()  
3240        public int nextIndex()
3241      {      {
3242        synchronized(sync)        return li.nextIndex();
       {  
         return ss.last();  
       }  
3243      }      }
3244      public SortedSet headSet(Object toElement)  
3245        public Object previous()
3246      {      {
3247        synchronized(sync)        return li.previous();
       {  
         return new SynchronizedSortedSet(sync, ss.headSet(toElement));  
       }  
3248      }      }
3249      public SortedSet tailSet(Object fromElement)  
3250        public int previousIndex()
3251      {      {
3252        synchronized(sync)        return li.previousIndex();
       {  
         return new SynchronizedSortedSet(sync, ss.tailSet(fromElement));  
       }  
3253      }      }
3254      public SortedSet subSet(Object fromElement, Object toElement)  
3255        public void set(Object o)
3256      {      {
3257        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return new SynchronizedSortedSet(sync,  
                                          ss.subSet(fromElement, toElement));  
       }  
3258      }      }
3259    }    } // class UnmodifiableListIterator
3260    
3261    private static class SynchronizedMap implements Map, Serializable    /**
3262       * Returns an unmodifiable view of the given map. This allows "read-only"
3263       * access, although changes in the backing map show up in this view.
3264       * Attempts to modify the map directly, or via collection views or their
3265       * iterators will fail with {@link UnsupportedOperationException}.
3266       * <p>
3267       *
3268       * The returned Map implements Serializable, but can only be serialized if
3269       * the map it wraps is likewise Serializable.
3270       *
3271       * @param m the map to wrap
3272       * @return a read-only view of the map
3273       * @see Serializable
3274       */
3275      public static Map unmodifiableMap(Map m)
3276    {    {
3277      Object sync;      return new UnmodifiableMap(m);
3278      Map m;    }
3279    
3280      public SynchronizedMap(Object sync, Map m)    /**
3281      {     * The implementation of {@link #unmodifiableMap(Map)}. This
3282        this.sync = sync;     * class name is required for compatibility with Sun's JDK serializability.
3283        this.m = m;     *
3284      }     * @author Eric Blake <ebb9@email.byu.edu>
3285      public SynchronizedMap(Map m)     */
3286      private static class UnmodifiableMap implements Map, Serializable
3287      {
3288        /**
3289         * Compatible with JDK 1.4.
3290         */
3291        private static final long serialVersionUID = -1034234728574286014L;
3292    
3293        /**
3294         * The wrapped map.
3295         * @serial the real map
3296         */
3297        private final Map m;
3298    
3299        /**
3300         * Cache the entry set.
3301         */
3302        private transient Set entries;
3303    
3304        /**
3305         * Cache the key set.
3306         */
3307        private transient Set keys;
3308    
3309        /**
3310         * Cache the value collection.
3311         */
3312        private transient Collection values;
3313    
3314        /**
3315         * Wrap a given map.
3316         * @param m the map to wrap
3317         * @throws NullPointerException if m is null
3318         */
3319        UnmodifiableMap(Map m)
3320      {      {
3321        this.m = m;        this.m = m;
3322        this.sync = this;        if (m == null)
3323            throw new NullPointerException();
3324      }      }
3325    
3326      public void clear()      public void clear()
3327      {      {
3328        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         m.clear();  
       }  
3329      }      }
3330    
3331      public boolean containsKey(Object key)      public boolean containsKey(Object key)
3332      {      {
3333        synchronized(sync)        return m.containsKey(key);
       {  
         return m.containsKey(key);  
       }  
3334      }      }
3335    
3336      public boolean containsValue(Object value)      public boolean containsValue(Object value)
3337      {      {
3338        synchronized(sync)        return m.containsValue(value);
       {  
         return m.containsValue(value);  
       }  
3339      }      }
3340    
     // This is one of the ickiest cases of nesting I've ever seen. It just  
     // means "return a SynchronizedSet, except that the iterator() method  
     // returns an SynchronizedIterator whos next() method returns a  
     // synchronized wrapper around its normal return value".  
3341      public Set entrySet()      public Set entrySet()
3342      {      {
3343        synchronized(sync)        if (entries == null)
3344            entries = new UnmodifiableEntrySet(m.entrySet());
3345          return entries;
3346        }
3347    
3348        /**
3349         * The implementation of {@link UnmodifiableMap#entrySet()}. This class
3350         * name is required for compatibility with Sun's JDK serializability.
3351         *
3352         * @author Eric Blake <ebb9@email.byu.edu>
3353         */
3354        private static final class UnmodifiableEntrySet extends UnmodifiableSet
3355          implements Serializable
3356        {
3357          /**
3358           * Compatible with JDK 1.4.
3359           */
3360          private static final long serialVersionUID = 7854390611657943733L;
3361    
3362          /**
3363           * Wrap a given set.
3364           * @param s the set to wrap
3365           */
3366          UnmodifiableEntrySet(Set s)
3367        {        {
3368          return new SynchronizedSet(sync, m.entrySet())          super(s);
3369          }
3370    
3371          // The iterator must return unmodifiable map entries.
3372          public Iterator iterator()
3373          {
3374            return new UnmodifiableIterator(c.iterator())
3375          {          {
3376            public Iterator iterator()            public Object next()
3377            {            {
3378              synchronized(SynchronizedMap.this.sync)              final Map.Entry e = (Map.Entry) super.next();
3379                return new Map.Entry()
3380              {              {
3381                return new SynchronizedIterator(SynchronizedMap.this.sync,                public boolean equals(Object o)
3382                                                c.iterator())                {
3383                {                  return e.equals(o);
3384                  public Object next()                }
3385                  {                public Object getKey()
3386                    synchronized(SynchronizedMap.this.sync)                {
3387                    {                  return e.getKey();
3388                      final Map.Entry e = (Map.Entry) super.next();                }
3389                      return new Map.Entry()                public Object getValue()
3390                      {                {
3391                        public Object getKey()                  return e.getValue();
3392                        {                }
3393                          synchronized(SynchronizedMap.this.sync)                public int hashCode()
3394                          {                {
3395                            return e.getKey();                  return e.hashCode();
3396                          }                }
3397                        }                public Object setValue(Object value)
3398                        public Object getValue()                {
3399                        {                  throw new UnsupportedOperationException();
3400                          synchronized(SynchronizedMap.this.sync)                }
3401                          {                public String toString()
3402                            return e.getValue();                {
3403                          }                  return e.toString();
3404                        }                }
3405                        public Object setValue(Object value)              };
3406                        {            }
                         synchronized(SynchronizedMap.this.sync)  
                         {  
                           return e.setValue(value);  
                         }  
                       }  
                       public int hashCode()  
                       {  
                         synchronized(SynchronizedMap.this.sync)  
                         {  
                           return e.hashCode();  
                         }  
                       }  
                       public boolean equals(Object o)  
                       {  
                         synchronized(SynchronizedMap.this.sync)  
                         {  
                           return e.equals(o);  
                         }  
                       }  
                     };  
                   }  
                 }  
               };  
             }  
           }  
3407          };          };
3408        }        }
3409      }      } // class UnmodifiableEntrySet
3410    
3411      public boolean equals(Object o)      public boolean equals(Object o)
3412      {      {
3413        synchronized(sync)        return m.equals(o);
       {  
         return m.equals(o);  
       }  
3414      }      }
3415    
3416      public Object get(Object key)      public Object get(Object key)
3417      {      {
3418        synchronized(sync)        return m.get(key);
       {  
         return m.get(key);  
       }  
3419      }      }
3420    
3421      public Object put(Object key, Object value)      public Object put(Object key, Object value)
3422      {      {
3423        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return m.put(key, value);  
       }  
3424      }      }
3425    
3426      public int hashCode()      public int hashCode()
3427      {      {
3428        synchronized(sync)        return m.hashCode();
       {  
         return m.hashCode();  
       }  
3429      }      }
3430    
3431      public boolean isEmpty()      public boolean isEmpty()
3432      {      {
3433        synchronized(sync)        return m.isEmpty();
       {  
         return m.isEmpty();  
       }  
3434      }      }
3435    
3436      public Set keySet()      public Set keySet()
3437      {      {
3438        synchronized(sync)        if (keys == null)
3439        {          keys = new UnmodifiableSet(m.keySet());
3440          return new SynchronizedSet(sync, m.keySet());        return keys;
       }  
3441      }      }
3442      public void putAll(Map map)  
3443        public void putAll(Map m)
3444      {      {
3445        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         m.putAll(map);  
       }  
3446      }      }
3447    
3448      public Object remove(Object o)      public Object remove(Object o)
3449      {      {
3450        synchronized(sync)        throw new UnsupportedOperationException();
       {  
         return m.remove(o);  
       }  
3451      }      }
3452    
3453      public int size()      public int size()
3454      {      {
3455        synchronized(sync)        return m.size();
       {  
         return m.size();  
       }  
3456      }      }
3457      public Collection values()  
3458        public String toString()
3459      {      {
3460        synchronized(sync)        return m.toString();
       {  
         return new SynchronizedCollection(sync, m.values());  
       }  
3461      }      }
3462      public String toString()  
3463        public Collection values()
3464      {      {
3465        synchronized(sync)        if (values == null)
3466        {          values = new UnmodifiableCollection(m.values());
3467          return m.toString();        return values;
       }  
3468      }      }
3469      } // class UnmodifiableMap
3470    
3471      /**
3472       * Returns an unmodifiable view of the given set. This allows
3473       * "read-only" access, although changes in the backing set show up
3474       * in this view. Attempts to modify the set directly or via iterators
3475       * will fail with {@link UnsupportedOperationException}.
3476       * <p>
3477       *
3478       * The returned Set implements Serializable, but can only be serialized if
3479       * the set it wraps is likewise Serializable.
3480       *
3481       * @param s the set to wrap
3482       * @return a read-only view of the set
3483       * @see Serializable
3484       */
3485      public static Set unmodifiableSet(Set s)
3486      {
3487        return new UnmodifiableSet(s);
3488    }    }
3489    
3490    private static class SynchronizedSortedMap extends SynchronizedMap    /**
3491      implements SortedMap     * The implementation of {@link #unmodifiableSet(Set)}. This class
3492       * name is required for compatibility with Sun's JDK serializability.
3493       *
3494       * @author Eric Blake <ebb9@email.byu.edu>
3495       */
3496      private static class UnmodifiableSet extends UnmodifiableCollection
3497        implements Set
3498    {    {
3499      // This is stored both here and in the superclass, to avoid excessive      /**
3500      // casting.       * Compatible with JDK 1.4.
3501      private SortedMap sm;       */
3502        private static final long serialVersionUID = -9215047833775013803L;
3503    
3504        /**
3505         * Wrap a given set.
3506         * @param s the set to wrap
3507         * @throws NullPointerException if s is null
3508         */
3509        UnmodifiableSet(Set s)
3510        {
3511          super(s);
3512        }
3513    
3514      public SynchronizedSortedMap(Object sync, SortedMap sm)      public boolean equals(Object o)
3515      {      {
3516        super(sync, sm);        return c.equals(o);
       this.sm = sm;  
3517      }      }
3518      public SynchronizedSortedMap(SortedMap sm)  
3519        public int hashCode()
3520        {
3521          return c.hashCode();
3522        }
3523      } // class UnmodifiableSet
3524    
3525      /**
3526       * Returns an unmodifiable view of the given sorted map. This allows
3527       * "read-only" access, although changes in the backing map show up in this
3528       * view. Attempts to modify the map directly, via subviews, via collection
3529       * views, or iterators, will fail with {@link UnsupportedOperationException}.
3530       * <p>
3531       *
3532       * The returned SortedMap implements Serializable, but can only be
3533       * serialized if the map it wraps is likewise Serializable.
3534       *
3535       * @param m the map to wrap
3536       * @return a read-only view of the map
3537       * @see Serializable
3538       */
3539      public static SortedMap unmodifiableSortedMap(SortedMap m)
3540      {
3541        return new UnmodifiableSortedMap(m);
3542      }
3543    
3544      /**
3545       * The implementation of {@link #unmodifiableSortedMap(SortedMap)}. This
3546       * class name is required for compatibility with Sun's JDK serializability.
3547       *
3548       * @author Eric Blake <ebb9@email.byu.edu>
3549       */
3550      private static class UnmodifiableSortedMap extends UnmodifiableMap
3551        implements SortedMap
3552      {
3553        /**
3554         * Compatible with JDK 1.4.
3555         */
3556        private static final long serialVersionUID = -8806743815996713206L;
3557    
3558        /**
3559         * The wrapped map; stored both here and in the superclass to avoid
3560         * excessive casting.
3561         * @serial the wrapped map
3562         */
3563        private final SortedMap sm;
3564    
3565        /**
3566         * Wrap a given map.
3567         * @param sm the map to wrap
3568         * @throws NullPointerException if sm is null
3569         */
3570        UnmodifiableSortedMap(SortedMap sm)
3571      {      {
3572        super(sm);        super(sm);
3573        this.sm = sm;        this.sm = sm;
# Line 1827  public class Collections Line 3575  public class Collections
3575    
3576      public Comparator comparator()      public Comparator comparator()
3577      {      {
3578        synchronized(sync)        return sm.comparator();
       {  
         return sm.comparator();  
       }  
3579      }      }
3580    
3581      public Object firstKey()      public Object firstKey()
3582      {      {
3583        synchronized(sync)        return sm.firstKey();
       {  
         return sm.firstKey();  
       }  
3584      }      }
3585    
3586        public SortedMap headMap(Object toKey)
3587        {
3588          return new UnmodifiableSortedMap(sm.headMap(toKey));
3589        }
3590    
3591      public Object lastKey()      public Object lastKey()
3592      {      {
3593        synchronized(sync)        return sm.lastKey();
       {  
         return sm.lastKey();  
       }  
3594      }      }
3595      public SortedMap headMap(Object toKey)  
3596        public SortedMap subMap(Object fromKey, Object toKey)
3597      {      {
3598        return new SynchronizedSortedMap(sync, sm.headMap(toKey));        return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));
3599      }      }
3600    
3601      public SortedMap tailMap(Object fromKey)      public SortedMap tailMap(Object fromKey)
3602      {      {
3603        return new SynchronizedSortedMap(sync, sm.tailMap(fromKey));        return new UnmodifiableSortedMap(sm.tailMap(fromKey));
3604      }      }
3605      public SortedMap subMap(Object fromKey, Object toKey)    } // class UnmodifiableSortedMap
3606    
3607      /**
3608       * Returns an unmodifiable view of the given sorted set. This allows
3609       * "read-only" access, although changes in the backing set show up
3610       * in this view. Attempts to modify the set directly, via subsets, or via
3611       * iterators, will fail with {@link UnsupportedOperationException}.
3612       * <p>
3613       *
3614       * The returns SortedSet implements Serializable, but can only be
3615       * serialized if the set it wraps is likewise Serializable.
3616       *
3617       * @param s the set to wrap
3618       * @return a read-only view of the set
3619       * @see Serializable
3620       */
3621      public static SortedSet unmodifiableSortedSet(SortedSet s)
3622      {
3623        return new UnmodifiableSortedSet(s);
3624      }
3625    
3626      /**
3627       * The implementation of {@link #synchronizedSortedMap(SortedMap)}. This
3628       * class name is required for compatibility with Sun's JDK serializability.
3629       *
3630       * @author Eric Blake <ebb9@email.byu.edu>
3631       */
3632      private static class UnmodifiableSortedSet extends UnmodifiableSet
3633        implements SortedSet
3634      {
3635        /**
3636         * Compatible with JDK 1.4.
3637         */
3638        private static final long serialVersionUID = -4929149591599911165L;
3639    
3640        /**
3641         * The wrapped set; stored both here and in the superclass to avoid
3642         * excessive casting.
3643         * @serial the wrapped set
3644         */
3645        private SortedSet ss;
3646    
3647        /**
3648         * Wrap a given set.
3649         * @param ss the set to wrap
3650         * @throws NullPointerException if ss is null
3651         */
3652        UnmodifiableSortedSet(SortedSet ss)
3653        {
3654          super(ss);
3655          this.ss = ss;
3656        }
3657    
3658        public Comparator comparator()
3659      {      {
3660        return new SynchronizedSortedMap(sync, sm.subMap(fromKey, toKey));        return ss.comparator();
3661      }      }
3662    }  
3663  }      public Object first()
3664        {
3665          return ss.first();
3666        }
3667    
3668        public SortedSet headSet(Object toElement)
3669        {
3670          return new UnmodifiableSortedSet(ss.headSet(toElement));
3671        }
3672    
3673        public Object last()
3674        {
3675          return ss.last();
3676        }
3677    
3678        public SortedSet subSet(Object fromElement, Object toElement)
3679        {
3680          return new UnmodifiableSortedSet(ss.subSet(fromElement, toElement));
3681        }
3682    
3683        public SortedSet tailSet(Object fromElement)
3684        {
3685          return new UnmodifiableSortedSet(ss.tailSet(fromElement));
3686        }
3687      } // class UnmodifiableSortedSet
3688    } // class Collections

Legend:
Removed from v.1.19  
changed lines
  Added in v.1.20

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26