home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / util / Collections.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  47.8 KB  |  1,425 lines

  1. /*
  2.  * @(#)Collections.java    1.21 98/03/18
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.util;
  16. import java.io.Serializable;
  17.  
  18. /**
  19.  * This class consists exclusively of static methods that operate on or
  20.  * return Collections.  It contains polymorphic algorithms that operate
  21.  * on collections, "views" and "wrappers", which return a new collection
  22.  * backed by a specified collection, and a few other odds and ends.
  23.  *
  24.  * @author  Josh Bloch
  25.  * @version 1.21 03/18/98
  26.  * @see        Collection
  27.  * @see        Set
  28.  * @see        List
  29.  * @see        Map
  30.  * @since JDK1.2
  31.  */
  32.  
  33. public class Collections {
  34.     // Algorithms
  35.  
  36.     /**
  37.      * Sorts the specified List into ascending order, according
  38.      * to the <i>natural comparison method</i> of its elements.  All
  39.      * elements in the List must implement the Comparable interface.
  40.      * Furthermore, all elements in the List must be <i>mutually
  41.      * comparable</i> (that is, e1.compareTo(e2) must not throw a
  42.      * typeMismatchException for any elements e1 and e2 in the List).
  43.      * <p>
  44.      * The sorting algorithm is a tuned quicksort, adapted from Jon
  45.      * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
  46.      * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
  47.      * 1993).  This algorithm offers n*log(n) performance on many data sets
  48.      * that cause other quicksorts to degrade to quadratic performance.
  49.      * <p>
  50.      * The specified List must be modifiable, but need not be resizable.
  51.      * This implementation dumps the specified List into an List, sorts
  52.      * the array, and iterates over the List resetting each element
  53.      * from the corresponding position in the array.  This avoids the
  54.      * n^2*log(n) performance that would result from attempting
  55.      * to sort a LinkedList in place.
  56.      *
  57.      * @param      list the List to be sorted.
  58.      * @exception ClassCastException List contains elements that are not
  59.      *          <i>mutually comparable</i> (for example, Strings and
  60.      *          Integers).
  61.      * @exception UnsupportedOperationException The specified List's
  62.      *          ListIterator not support the set operation.
  63.      * @see Comparable
  64.      */
  65.     public static void sort(List list) {
  66.     Object a[] = list.toArray();
  67.     Arrays.sort(a);
  68.     ListIterator i = list.listIterator();
  69.     for (int j=0; j<a.length; j++) {
  70.         i.next();
  71.         i.set(a[j]);
  72.     }
  73.     }
  74.  
  75.     /**
  76.      * Sorts the specified List according to the order induced by the
  77.      * specified Comparator.  All elements in the List must be <i>mutually
  78.      * comparable</i> by the specified comparator (that is,
  79.      * comparator.compare(e1, e2) must not throw a typeMismatchException for
  80.      * any elements e1 and e2 in the List).
  81.      * <p>
  82.      * The sorting algorithm is a tuned quicksort, adapted from Jon
  83.      * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
  84.      * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
  85.      * 1993).  This algorithm offers n*log(n) performance on many data sets
  86.      * that cause other quicksorts to degrade to quadratic performance.
  87.      * <p>
  88.      * The specified List must be modifiable, but need not be resizable.
  89.      * This implementation dumps the specified List into an array, sorts
  90.      * the array, and iterates over the List resetting each element
  91.      * from the corresponding position in the array.  This avoids the
  92.      * n^2*log(n) performance that would result from attempting
  93.      * to sort a LinkedList in place.
  94.      *
  95.      * @param      list the List to be sorted.
  96.      * @exception ClassCastException List contains elements that are not
  97.      *          <i>mutually comparable</i> with the specified Comparator.
  98.      * @exception UnsupportedOperationException The specified List's did
  99.      *          ListIterator not support the set operation.
  100.      * @see Comparator
  101.      */
  102.     public static void sort(List list, Comparator c) {
  103.     Object a[] = list.toArray();
  104.     Arrays.sort(a, c);
  105.     ListIterator i = list.listIterator();
  106.     for (int j=0; j<a.length; j++) {
  107.         i.next();
  108.         i.set(a[j]);
  109.     }
  110.     }
  111.  
  112.  
  113.     /**
  114.      * Searches the specified List for the specified Object using the binary
  115.      * search algorithm.  The List must be sorted into ascending order
  116.      * according to the <i>natural comparison method</i> of its elements (as by
  117.      * Sort(List), above) prior to making this call.  If it is not sorted,
  118.      * the results are undefined: in particular, the call may enter an infinite
  119.      * loop.  If the List contains multiple elements equal to the specified
  120.      * Object, there is no guarantee which instance will be found.
  121.      *<p>
  122.      * This method will run in log(n) time for a "random access" List (which
  123.      * provides near-constant-time positional access) like a Vector.  It may
  124.      * run in n*log(n) time if it is called on a "sequential access" List
  125.      * (which provides linear-time positional access).  If the specified List
  126.      * is an instanceof AbstracSequentialList, this method will do a
  127.      * sequential search instead of a binary search; this offers linear
  128.      * performance instead of n*log(n) performance if this method is called on
  129.      * a LinkedList.
  130.      *
  131.      * @param      list the List to be searched.
  132.      * @param      key the key to be searched for.
  133.      * @return index of the search key, if it is contained in the List;
  134.      *           otherwise, (-(<i>insertion point</i>) - 1).  The <i>insertion
  135.      *           point</i> is defined as the the point at which the value would
  136.      *            be inserted into the List: the index of the first element
  137.      *           greater than the value, or list.size(), if all elements in
  138.      *           the List are less than the specified value.  Note that this
  139.      *           guarantees that the return value will be >= 0 if and only
  140.      *           if the Object is found.
  141.      * @exception ClassCastException List contains elements that are not
  142.      *          <i>mutually comparable</i> (for example, Strings and
  143.      *          Integers), or the search key in not mutually comparable
  144.      *          with the elements of the List.
  145.      * @see Comparable
  146.      * @see #sort(List)
  147.      */
  148.     public static int binarySearch(List list, Object key) {
  149.     // Do a sequential search if appropriate
  150.     if (list instanceof AbstractSequentialList) {
  151.         ListIterator i = list.listIterator();
  152.         while (i.hasNext()) {
  153.         int cmp = ((Comparable)(i.next())).compareTo(key);
  154.         if (cmp == 0)
  155.             return i.previousIndex();
  156.         else if (cmp > 0)
  157.             return -i.nextIndex();  // key not found.
  158.         }
  159.         return -i.nextIndex();  // key not found, list exhausted
  160.     }
  161.  
  162.     // Otherwise, do a binary search
  163.     int low = 0;
  164.     int high = list.size()-1;
  165.  
  166.     while (low <= high) {
  167.         int mid =(low + high)/2;
  168.         Object midVal = list.get(mid);
  169.         int cmp = ((Comparable)midVal).compareTo(key);
  170.  
  171.         if (cmp < 0)
  172.         low = mid + 1;
  173.         else if (cmp > 0)
  174.         high = mid - 1;
  175.         else
  176.         return mid; // key found
  177.     }
  178.     return -(low + 1);  // key not found
  179.     }
  180.  
  181.     /**
  182.      * Searches the specified List for the specified Object using the binary
  183.      * search algorithm.  The List must be sorted into ascending order
  184.      * according to the specified Comparator (as by Sort(List, Comparator),
  185.      * above), prior to making this call.
  186.      *<p>
  187.      * This method will run in log(n) time for a "random access" List (which
  188.      * provides near-constant-time positional access) like a Vector.  It may
  189.      * run in n*log(n) time if it is called on a "sequential access" List
  190.      * (which provides linear-time positional access).  If the specified List
  191.      * is an instanceof AbstracSequentialList, this method will do a
  192.      * sequential search instead of a binary search; this offers linear
  193.      * performance instead of n*log(n) performance if this method is called on
  194.      * a LinkedList.
  195.      *
  196.      * @param      list the List to be searched.
  197.      * @param      key the key to be searched for.
  198.      * @return index of the search key, if it is contained in the List;
  199.      *           otherwise, (-(<i>insertion point</i>) - 1).  The <i>insertion
  200.      *           point</i> is defined as the the point at which the value would
  201.      *            be inserted into the List: the index of the first element
  202.      *           greater than the value, or list.size(), if all elements in
  203.      *           the List are less than the specified value.  Note that this
  204.      *           guarantees that the return value will be >= 0 if and only
  205.      *           if the Object is found.
  206.      * @exception ClassCastException List contains elements that are not
  207.      *          <i>mutually comparable</i> with the specified Comparator,
  208.      *          or the search key in not mutually comparable with the
  209.      *          elements of the List using this Comparator.
  210.      * @see Comparable
  211.      * @see #sort(List, Comparator)
  212.      */
  213.     public static int binarySearch(List list, Object key, Comparator c) {
  214.     // Do a sequential search if appropriate
  215.     if (list instanceof AbstractSequentialList) {
  216.         ListIterator i = list.listIterator();
  217.         while (i.hasNext()) {
  218.         int cmp = c.compare(i.next(), key);
  219.         if (cmp == 0)
  220.             return i.previousIndex();
  221.         else if (cmp > 0)
  222.             return -i.nextIndex();  // key not found.
  223.         }
  224.         return -i.nextIndex();  // key not found, list exhausted
  225.     }
  226.  
  227.     // Otherwise, do a binary search
  228.     int low = 0;
  229.     int high = list.size()-1;
  230.  
  231.     while (low <= high) {
  232.         int mid =(low + high)/2;
  233.         Object midVal = list.get(mid);
  234.         int cmp = c.compare(midVal, key);
  235.  
  236.         if (cmp < 0)
  237.         low = mid + 1;
  238.         else if (cmp > 0)
  239.         high = mid - 1;
  240.         else
  241.         return mid; // key found
  242.     }
  243.     return -(low + 1);  // key not found
  244.     }
  245.  
  246.     /**
  247.      * Returns the minimum element of the given Collection, according
  248.      * to the <i>natural comparison method</i> of its elements.  All
  249.      * elements in the Collection must implement the Comparable interface.
  250.      * Furthermore, all elements in the Collection must be <i>mutually
  251.      * comparable</i> (that is, e1.compareTo(e2) must not throw a
  252.      * typeMismatchException for any elements e1 and e2 in the Collection).
  253.      * <p>
  254.      * This method iterates over the entire Collection, hence it requires
  255.      * time proportional to the size of the Collection.
  256.      *
  257.      * @param coll the collection whose minimum element is to be determined.
  258.      * @exception ClassCastException Collection contains elements that are not
  259.      *          <i>mutually comparable</i> (for example, Strings and
  260.      *          Integers).
  261.      * @exception NoSuchElementException Collection is empty.
  262.      * 
  263.      * @see Comparable
  264.      */
  265.     public static Object min(Collection coll) {
  266.     Iterator i = coll.iterator();
  267.     Comparable candidate = (Comparable)(i.next());
  268.     while (i.hasNext()) {
  269.         Comparable next = (Comparable)(i.next());
  270.         if (next.compareTo(candidate) < 0)
  271.         candidate = next;
  272.     }
  273.     return candidate;
  274.     }
  275.  
  276.     /**
  277.      * Returns the minimum element of the given Collection, according to the
  278.      * order induced by the specified Comparator.  All elements in the
  279.      * Collection must be <i>mutually comparable</i> by the specified
  280.      * comparator (that is, comparator.compare(e1, e2) must not throw a
  281.      * typeMismatchException for any elements e1 and e2 in the Collection).
  282.      * <p>
  283.      * This method iterates over the entire Collection, hence it requires
  284.      * time proportional to the size of the Collection.
  285.      *
  286.      * @param coll the collection whose minimum element is to be determined.
  287.      * @exception ClassCastException Collection contains elements that are not
  288.      *          <i>mutually comparable</i> with the specified Comparator.
  289.      * @exception NoSuchElementException Collection is empty.
  290.      * 
  291.      * @see Comparable
  292.      */
  293.     public static Object min(Collection coll, Comparator comp) {
  294.     Iterator i = coll.iterator();
  295.     Object candidate = i.next();
  296.     while (i.hasNext()) {
  297.         Object next = i.next();
  298.         if (comp.compare(next, candidate) < 0)
  299.         candidate = next;
  300.     }
  301.     return candidate;
  302.     }
  303.  
  304.     /**
  305.      * Returns the maximum element of the given Collection, according
  306.      * to the <i>natural comparison method</i> of its elements.  All
  307.      * elements in the Collection must implement the Comparable interface.
  308.      * Furthermore, all elements in the Collection must be <i>mutually
  309.      * comparable</i> (that is, e1.compareTo(e2) must not throw a
  310.      * typeMismatchException for any elements e1 and e2 in the Collection).
  311.      * <p>
  312.      * This method iterates over the entire Collection, hence it requires
  313.      * time proportional to the size of the Collection.
  314.      *
  315.      * @param coll the collection whose maximum element is to be determined.
  316.      * @exception ClassCastException Collection contains elements that are not
  317.      *          <i>mutually comparable</i> (for example, Strings and
  318.      *          Integers).
  319.      * @exception NoSuchElementException Collection is empty.
  320.      * 
  321.      * @see Comparable
  322.      */
  323.     public static Object max(Collection coll) {
  324.     Iterator i = coll.iterator();
  325.     Comparable candidate = (Comparable)(i.next());
  326.     while (i.hasNext()) {
  327.         Comparable next = (Comparable)(i.next());
  328.         if (next.compareTo(candidate) > 0)
  329.         candidate = next;
  330.     }
  331.     return candidate;
  332.     }
  333.  
  334.  
  335.     /**
  336.      * Returns the maximum element of the given Collection, according to the
  337.      * order induced by the specified Comparator.  All elements in the
  338.      * Collection must be <i>mutually comparable</i> by the specified
  339.      * comparator (that is, comparator.compare(e1, e2) must not throw a
  340.      * typeMismatchException for any elements e1 and e2 in the Collection).
  341.      * <p>
  342.      * This method iterates over the entire Collection, hence it requires
  343.      * time proportional to the size of the Collection.
  344.      *
  345.      * @param coll the collection whose maximum element is to be determined.
  346.      * @exception ClassCastException Collection contains elements that are not
  347.      *          <i>mutually comparable</i> with the specified Comparator.
  348.      * @exception NoSuchElementException Collection is empty.
  349.      * 
  350.      * @see Comparable
  351.      */
  352.     public static Object max(Collection coll, Comparator comp) {
  353.     Iterator i = coll.iterator();
  354.     Object candidate = i.next();
  355.     while (i.hasNext()) {
  356.         Object next = i.next();
  357.         if (comp.compare(next, candidate) > 0)
  358.         candidate = next;
  359.     }
  360.     return candidate;
  361.     }
  362.  
  363.     // List Views
  364.  
  365.     /**
  366.      * Returns a List backed by the specified List that represents the portion
  367.      * of the specified List whose index ranges from fromIndex (inclusive) to
  368.      * toIndex (exclusive).  The returned List is not resizable.  (Its size
  369.      * is fixed at (toIndex - fromIndex).)  The returned List is mutable iff
  370.      * the specified List is mutable.  Changes to the returned List "write
  371.      * through" to the specified List, and vice-versa.
  372.      * <p>
  373.      * If the caller wants a List that is independent of the input List,
  374.      * and free of the restrictions noted above, he should immediately
  375.      * copy the returned List into a new List, for example:
  376.      * <pre>
  377.      *     Vector v = new Vector(Collections.subList(myList, 17, 42));
  378.      * </pre>
  379.      *
  380.      * @param list the List whose subList is to be returned.
  381.      * @param fromIndex the index (in this List) of the first element to
  382.      *          appear in the subList.
  383.      * @param toIndex the index (in this List) following the last element to
  384.      *          appear in the subList.
  385.      * @exception IndexOutOfBoundsException fromIndex or toIndex is out
  386.      *          of range (fromIndex < 0 || fromIndex > size ||
  387.      *          toIndex < 0 || toIndex > size).
  388.      * @exception IllegalArgumentException fromIndex > toIndex.
  389.      */
  390.     public static List subList(List list, int fromIndex, int toIndex) {
  391.     return new SubList(list, fromIndex, toIndex);
  392.     }
  393.  
  394.     /**
  395.      * SubList - Implements a SubList view backed by an arbitrary List.
  396.      */
  397.     static class SubList extends AbstractList {
  398.     private List backer;
  399.     private int offset;
  400.     private int size;
  401.  
  402.     SubList(List list, int fromIndex, int toIndex) {
  403.         backer = list;
  404.         offset = fromIndex;
  405.         size = toIndex - fromIndex;
  406.  
  407.         if (size<0)
  408.         throw new IllegalArgumentException("fromIndex < toIndex");
  409.  
  410.         int backerSize = backer.size();
  411.         if (fromIndex < 0 || fromIndex > backerSize ||
  412.         toIndex   < 0 || toIndex   > backerSize)
  413.         throw new IndexOutOfBoundsException();
  414.     }
  415.  
  416.     public int size() {
  417.         return size;
  418.     }
  419.  
  420.     public Iterator iterator() {
  421.         return listIterator();
  422.     }
  423.  
  424.     public Object get(int index) {
  425.         rangeCheck(index);
  426.         return backer.get(index + offset);
  427.     }
  428.  
  429.     public Object set(int index, Object element) {
  430.         rangeCheck(index);
  431.         return backer.set(index + offset, element);
  432.     }
  433.  
  434.     public int indexOf(Object o, int index) {
  435.         rangeCheck(index);
  436.         ListIterator i = backer.listIterator(index + offset);
  437.  
  438.         if (o==null) {
  439.         for(int j=index; j<size; j++)
  440.             if (i.next()==null)
  441.             return i.previousIndex() - offset;
  442.         } else {
  443.         for(int j=index; j<size; j++)
  444.             if (o.equals(i.next()))
  445.             return i.previousIndex() - offset;
  446.         }
  447.         return -1;
  448.     }
  449.  
  450.     public int lastIndexOf(Object o, int index) {
  451.         rangeCheck(index);
  452.         ListIterator i = backer.listIterator(index + offset + 1);
  453.  
  454.         if (o==null) {
  455.         for(int j=index; j>=0; j--)
  456.             if (i.previous()==null)
  457.             return i.nextIndex() - offset;
  458.         } else {
  459.         for(int j=index; j>=0; j--)
  460.             if (o.equals(i.previous()))
  461.             return i.nextIndex() - offset;
  462.         }
  463.         return -1;
  464.     }
  465.  
  466.     public ListIterator listIterator(final int index) {
  467.         if (index<0 || index>size)
  468.         throw new IndexOutOfBoundsException(
  469.             "Index: "+index+", Size: "+size);
  470.  
  471.         return new ListIterator() {
  472.         private ListIterator i = backer.listIterator(index+offset);
  473.  
  474.         public boolean hasNext() {
  475.             return nextIndex() < size;
  476.         }
  477.  
  478.         public Object next() {
  479.             if (hasNext())
  480.             return i.next();
  481.             else
  482.             throw new NoSuchElementException();
  483.         }
  484.  
  485.         public boolean hasPrevious() {
  486.             return previousIndex() >= 0;
  487.         }
  488.  
  489.         public Object previous() {
  490.             if (hasPrevious())
  491.             return i.previous();
  492.             else
  493.             throw new NoSuchElementException();
  494.         }
  495.  
  496.         public int nextIndex() {
  497.             return i.nextIndex() - offset;
  498.         }
  499.  
  500.         public int previousIndex() {
  501.             return i.previousIndex() - offset;
  502.         }
  503.  
  504.         public void remove() {
  505.             throw new UnsupportedOperationException();
  506.         }
  507.  
  508.         public void set(Object o) {
  509.             i.set(o);
  510.         }
  511.  
  512.         public void add(Object o) {
  513.             throw new UnsupportedOperationException();
  514.         }
  515.         };
  516.     }
  517.  
  518.     private void rangeCheck(int index) {
  519.         if (index<0 || index>=size)
  520.         throw new IndexOutOfBoundsException("Index: "+index+
  521.                             ",Size: "+size);
  522.     }
  523.     }
  524.  
  525.  
  526.     // Unmodifiable Wrappers
  527.  
  528.     /**
  529.      * Returns an unmodifiable view of the specified Collection.  This method
  530.      * allows modules to provide users with "read-only" access to internal
  531.      * Collections. Query operations on the returned Collection "read through"
  532.      * to the specified Collection, and attempts to modify the returned
  533.      * Collection, whether direct or via its Iterator, result in an
  534.      * UnsupportedOperationException.
  535.      * <p>
  536.      * The returned Collection does <em>not</em> pass the hashCode and
  537.      * equals operations through to the backing Collection, but relies
  538.      * on Object's equals and hashCode methods.  This is necessary to
  539.      * preserve the contracts of these operations in the case that the
  540.      * backing Collection is a Set or a List.
  541.      * <p>
  542.      * The returned Collection will be Serializable if the specified Collection
  543.      * is Serializable. 
  544.      *
  545.      * @param c the Collection for which an unmodifiable view is to be
  546.      *        returned.
  547.      */
  548.     public static Collection unmodifiableCollection(Collection c) {
  549.     return new UnmodifiableCollection(c);
  550.     }
  551.  
  552.     static class UnmodifiableCollection implements Collection, Serializable {
  553.     private Collection c;
  554.  
  555.     UnmodifiableCollection(Collection c) {this.c = c;}
  556.  
  557.     public int size()             {return c.size();}
  558.     public boolean isEmpty()         {return c.isEmpty();}
  559.     public boolean contains(Object o)   {return c.contains(o);}
  560.     public Object[] toArray()         {return c.toArray();}
  561.     public Object[] toArray(Object[] a) {return c.toArray(a);}
  562.  
  563.     public Iterator iterator() {
  564.         return new Iterator() {
  565.         Iterator i = c.iterator();
  566.  
  567.         public boolean hasNext() {return i.hasNext();}
  568.         public Object next()      {return i.next();}
  569.         public void remove() {
  570.             throw new UnsupportedOperationException();
  571.                 }
  572.         };
  573.         }
  574.  
  575.     public boolean add(Object o){
  576.         throw new UnsupportedOperationException();
  577.         }
  578.     public boolean remove(Object o) {
  579.         throw new UnsupportedOperationException();
  580.         }
  581.  
  582.     public boolean containsAll(Collection coll) {
  583.         return c.containsAll(coll);
  584.         }
  585.     public boolean addAll(Collection coll) {
  586.         throw new UnsupportedOperationException();
  587.         }
  588.     public boolean removeAll(Collection coll) {
  589.         throw new UnsupportedOperationException();
  590.         }
  591.     public boolean retainAll(Collection coll) {
  592.         throw new UnsupportedOperationException();
  593.         }
  594.     public void clear() {
  595.         throw new UnsupportedOperationException();
  596.         }
  597.     }
  598.  
  599.     /**
  600.      * Returns an unmodifiable view of the specified Set.  This method allows
  601.      * modules to provide users with "read-only" access to internal
  602.      * Sets. Query operations on the returned Set "read through" to the
  603.      * specified Set, and attempts to modify the returned Set, whether direct
  604.      * or via its Iterator, result in an UnsupportedOperationException.
  605.      * <p>
  606.      * The returned Set will be Serializable if the specified Set
  607.      * is Serializable. 
  608.      *
  609.      * @param s the Set for which an unmodifiable view is to be returned.
  610.      */
  611.  
  612.     public static Set unmodifiableSet(Set s) {
  613.     return new UnmodifiableSet(s);
  614.     }
  615.  
  616.     static class UnmodifiableSet extends UnmodifiableCollection
  617.                      implements Set, Serializable {
  618.     UnmodifiableSet(Set s)         {super(s);}
  619.  
  620.     public boolean equals(Object o) {return c.equals(o);}
  621.     public int hashCode()         {return c.hashCode();}
  622.     }
  623.  
  624.     /**
  625.      * Returns an unmodifiable view of the specified SortedSet.  This method
  626.      * allows modules to provide users with "read-only" access to internal
  627.      * SortedSets.  Query operations on the returned SortedSet "read through"
  628.      * to the specified SortedSet.  Attempts to modify the returned
  629.      * SortedSet, whether direct, via its Iterator, or via its subSet,
  630.      * headSet, or tailSet views, result in an UnsupportedOperationException.
  631.      *<p>
  632.      * The returned SortedSet will be Serializable if the specified SortedSet
  633.      * is Serializable. 
  634.      *
  635.      * @param s the SortedSet for which an unmodifiable view is to be returned.
  636.      */
  637.     public static SortedSet unmodifiableSortedSet(SortedSet s) {
  638.     return new UnmodifiableSortedSet(s);
  639.     }
  640.  
  641.     static class UnmodifiableSortedSet extends UnmodifiableSet
  642.                      implements SortedSet, Serializable {
  643.         private SortedSet ss;
  644.  
  645.     UnmodifiableSortedSet(SortedSet s) {super(s); ss = s;}
  646.  
  647.         public Comparator comparator()     {return ss.comparator();}
  648.  
  649.         public SortedSet subSet(Object fromElement, Object toElement) {
  650.             return new UnmodifiableSortedSet(ss.subSet(fromElement,toElement));
  651.         }
  652.         public SortedSet headSet(Object toElement) {
  653.             return new UnmodifiableSortedSet(ss.headSet(toElement));
  654.         }
  655.         public SortedSet tailSet(Object fromElement) {
  656.             return new UnmodifiableSortedSet(ss.tailSet(fromElement));
  657.         }
  658.  
  659.         public Object first()                {return ss.first();}
  660.         public Object last()                 {return ss.last();}
  661.     }
  662.  
  663.     /**
  664.      * Returns an unmodifiable view of the specified List.  This method allows
  665.      * modules to provide users with "read-only" access to internal
  666.      * Lists. Query operations on the returned List "read through" to the
  667.      * specified List, and attempts to modify the returned List, whether direct
  668.      * or via its Iterator, result in an UnsupportedOperationException.
  669.      * <p>
  670.      * The returned List will be Serializable if the specified List
  671.      * is Serializable. 
  672.      *
  673.      * @param list the List for which an unmodifiable view is to be returned.
  674.      */
  675.  
  676.     public static List unmodifiableList(List list) {
  677.     return new UnmodifiableList(list);
  678.     }
  679.  
  680.     static class UnmodifiableList extends UnmodifiableCollection
  681.                       implements List {
  682.     private List list;
  683.  
  684.     UnmodifiableList(List list) {
  685.         super(list);
  686.         this.list = list;
  687.     }
  688.  
  689.     public boolean equals(Object o) {return list.equals(o);}
  690.     public int hashCode()         {return list.hashCode();}
  691.  
  692.     public Object get(int index) {return list.get(index);}
  693.     public Object set(int index, Object element) {
  694.         throw new UnsupportedOperationException();
  695.         }
  696.     public void add(int index, Object element) {
  697.         throw new UnsupportedOperationException();
  698.         }
  699.     public Object remove(int index) {
  700.         throw new UnsupportedOperationException();
  701.         }
  702.     public int indexOf(Object o)            {return list.indexOf(o);}
  703.     public int indexOf(Object o, int i)     {return list.indexOf(o, i);}
  704.     public int lastIndexOf(Object o)        {return list.lastIndexOf(o);}
  705.     public int lastIndexOf(Object o, int i) {return list.lastIndexOf(o,i);}
  706.     public void removeRange(int fromIndex, int toIndex) {
  707.         throw new UnsupportedOperationException();
  708.         }
  709.     public boolean addAll(int index, Collection c) {
  710.         throw new UnsupportedOperationException();
  711.         }
  712.     public ListIterator listIterator()     {return listIterator(0);}
  713.  
  714.     public ListIterator listIterator(final int index) {
  715.         return new ListIterator() {
  716.         ListIterator i = list.listIterator(index);
  717.  
  718.         public boolean hasNext()     {return i.hasNext();}
  719.         public Object next()         {return i.next();}
  720.         public boolean hasPrevious() {return i.hasPrevious();}
  721.         public Object previous()     {return i.previous();}
  722.         public int nextIndex()       {return i.nextIndex();}
  723.         public int previousIndex()   {return i.previousIndex();}
  724.  
  725.         public void remove() {
  726.             throw new UnsupportedOperationException();
  727.                 }
  728.         public void set(Object o) {
  729.             throw new UnsupportedOperationException();
  730.                 }
  731.         public void add(Object o) {
  732.             throw new UnsupportedOperationException();
  733.                 }
  734.         };
  735.     }
  736.     }
  737.  
  738.     /**
  739.      * Returns an unmodifiable view of the specified Map.  This method
  740.      * allows modules to provide users with "read-only" access to internal
  741.      * Maps. Query operations on the returned Map "read through"
  742.      * to the specified Map, and attempts to modify the returned
  743.      * Map, whether direct or via its Collection views, result in an
  744.      * UnsupportedOperationException.
  745.      * <p>
  746.      * The returned Map will be Serializable if the specified Map
  747.      * is Serializable. 
  748.      *
  749.      * @param m the Map for which an unmodifiable view is to be returned.
  750.      */
  751.     public static Map unmodifiableMap(Map m) {
  752.     return new UnmodifiableMap(m);
  753.     }
  754.  
  755.     private static class UnmodifiableMap implements Map, Serializable {
  756.     private final Map m;
  757.  
  758.     UnmodifiableMap(Map m)                  {this.m = m;}
  759.  
  760.     public int size()                  {return m.size();}
  761.     public boolean isEmpty()              {return m.isEmpty();}
  762.     public boolean containsKey(Object key)   {return m.containsKey(key);}
  763.     public boolean containsValue(Object val) {return m.containsValue(val);}
  764.     public Object get(Object key)              {return m.get(key);}
  765.  
  766.     public Object put(Object key, Object value) {
  767.         throw new UnsupportedOperationException();
  768.         }
  769.     public Object remove(Object key) {
  770.         throw new UnsupportedOperationException();
  771.         }
  772.     public void putAll(Map t) {
  773.         throw new UnsupportedOperationException();
  774.         }
  775.     public void clear() {
  776.         throw new UnsupportedOperationException();
  777.         }
  778.  
  779.     private transient Set keySet = null;
  780.     private transient Set entries = null;
  781.     private transient Collection values = null;
  782.  
  783.     public Set keySet() {
  784.         if (keySet==null)
  785.         keySet = unmodifiableSet(m.keySet());
  786.         return keySet;
  787.     }
  788.  
  789.     public Set entries() {
  790.         if (entries==null)
  791.         entries = unmodifiableSet(m.entries());
  792.         return entries;
  793.     }
  794.  
  795.     public Collection values() {
  796.         if (values==null)
  797.         values = unmodifiableCollection(m.values());
  798.         return values;
  799.     }
  800.  
  801.     public boolean equals(Object o) {return m.equals(o);}
  802.     public int hashCode()           {return m.hashCode();}
  803.     }
  804.  
  805.     /**
  806.      * Returns an unmodifiable view of the specified SortedMap.  This method
  807.      * allows modules to provide users with "read-only" access to internal
  808.      * SortedMaps. Query operations on the returned SortedMap "read through"
  809.      * to the specified SortedMap.  Attempts to modify the returned
  810.      * SortedMap, whether direct, via its Collection views, or via its
  811.      * subMap, headMap, or tailMap views, result in an
  812.      * UnsupportedOperationException.
  813.      * <p>
  814.      * The returned SortedMap will be Serializable if the specified SortedMap
  815.      * is Serializable. 
  816.      *
  817.      * @param m the SortedMap for which an unmodifiable view is to be returned.
  818.      */
  819.     public static SortedMap unmodifiableSortedMap(SortedMap m) {
  820.     return new UnmodifiableSortedMap(m);
  821.     }
  822.  
  823.     static class UnmodifiableSortedMap extends UnmodifiableMap
  824.                      implements SortedMap, Serializable {
  825.         private SortedMap sm;
  826.  
  827.     UnmodifiableSortedMap(SortedMap m) {super(m); sm = m;}
  828.  
  829.         public Comparator comparator()     {return sm.comparator();}
  830.  
  831.         public SortedMap subMap(Object fromKey, Object toKey) {
  832.             return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));
  833.         }
  834.         public SortedMap headMap(Object toKey) {
  835.             return new UnmodifiableSortedMap(sm.headMap(toKey));
  836.         }
  837.         public SortedMap tailMap(Object fromKey) {
  838.             return new UnmodifiableSortedMap(sm.tailMap(fromKey));
  839.         }
  840.  
  841.         public Object firstKey()           {return sm.firstKey();}
  842.         public Object lastKey()            {return sm.lastKey();}
  843.     }
  844.  
  845.  
  846.     // Synch Wrappers
  847.  
  848.     /**
  849.      * Returns a synchronized (thread-safe) Collection backed by the specified
  850.      * Collection. In order to guarantee serial access, it is critical that
  851.      * <strong>all</strong> access to the backing Collection is accomplished
  852.      * through the returned Collection.
  853.      * <p>
  854.      * It is imperative that the user manually synchronize on the returned
  855.      * Collection when iterating over it:
  856.      * <pre>
  857.      *  Collection c = synchronizedCollection(myCollection);
  858.      *     ...
  859.      *  synchronized(c) {
  860.      *      Iterator i = c.iterator(); // Must be in the synchronized block
  861.      *      while (i.hasNext())
  862.      *         foo(i.next();
  863.      *  }
  864.      * </pre>
  865.      * Failure to follow this advice may result in non-deterministic behavior.
  866.      * <p>
  867.      * The returned Collection does <em>not</em> pass the hashCode and
  868.      * equals operations through to the backing Collection, but relies
  869.      * on Object's equals and hashCode methods.  This is necessary to
  870.      * preserve the contracts of these operations in the case that the
  871.      * backing Collection is a Set or a List.
  872.      * <p>
  873.      * The returned Collection will be Serializable if the specified Collection
  874.      * is Serializable. 
  875.      *
  876.      * @param c the Collection to be "wrapped" in a synchronized Collection.
  877.      */
  878.     public static Collection synchronizedCollection(Collection c) {
  879.     return new SynchronizedCollection(c);
  880.     }
  881.  
  882.     static class SynchronizedCollection implements Collection, Serializable {
  883.     private Collection c;       // Backing Collection
  884.     private Object       mutex;  // Object on which to synchronize
  885.  
  886.     SynchronizedCollection(Collection c) {
  887.         this.c = c; mutex = this;
  888.         }
  889.     SynchronizedCollection(Collection c, Object mutex) {
  890.         this.c = c; this.mutex = mutex;
  891.         }
  892.  
  893.     public int size() {
  894.         synchronized(mutex) {return c.size();}
  895.         }
  896.     public boolean isEmpty() {
  897.         synchronized(mutex) {return c.isEmpty();}
  898.         }
  899.     public boolean contains(Object o) {
  900.         synchronized(mutex) {return c.contains(o);}
  901.         }
  902.     public Object[] toArray() {
  903.         synchronized(mutex) {return c.toArray();}
  904.         }
  905.     public Object[] toArray(Object[] a) {
  906.         synchronized(mutex) {return c.toArray(a);}
  907.         }
  908.  
  909.     public Iterator iterator() {
  910.             return c.iterator(); // Must be manually synched by user!
  911.         }
  912.  
  913.     public boolean add(Object o) {
  914.         synchronized(mutex) {return c.add(o);}
  915.         }
  916.     public boolean remove(Object o) {
  917.         synchronized(mutex) {return c.remove(o);}
  918.         }
  919.  
  920.     public boolean containsAll(Collection coll) {
  921.         synchronized(mutex) {return c.containsAll(coll);}
  922.         }
  923.     public boolean addAll(Collection coll) {
  924.         synchronized(mutex) {return c.addAll(coll);}
  925.         }
  926.     public boolean removeAll(Collection coll) {
  927.         synchronized(mutex) {return c.removeAll(coll);}
  928.         }
  929.     public boolean retainAll(Collection coll) {
  930.         synchronized(mutex) {return c.retainAll(coll);}
  931.         }
  932.     public void clear() {
  933.         synchronized(mutex) {c.clear();}
  934.         }
  935.     }
  936.  
  937.     /**
  938.      * Returns a synchronized (thread-safe) Set backed by the specified
  939.      * Set. In order to guarantee serial access, it is critical that
  940.      * <strong>all</strong> access to the backing Set is accomplished
  941.      * through the returned Set.
  942.      * <p>
  943.      * It is imperative that the user manually synchronize on the returned
  944.      * Set when iterating over it:
  945.      * <pre>
  946.      *  Set s = synchronizedSet(new HashSet());
  947.      *      ...
  948.      *  synchronized(s) {
  949.      *      Iterator i = s.iterator(); // Must be in the synchronized block
  950.      *      while (i.hasNext())
  951.      *          foo(i.next();
  952.      *  }
  953.      * </pre>
  954.      * Failure to follow this advice may result in non-deterministic behavior.
  955.      * <p>
  956.      * The returned Set will be Serializable if the specified Set is
  957.      * Serializable.
  958.      *
  959.      * @param s the Set to be "wrapped" in a synchronized Set.
  960.      */
  961.     public static Set synchronizedSet(Set s) {
  962.     return new SynchronizedSet(s);
  963.     }
  964.  
  965.     static class SynchronizedSet extends SynchronizedCollection
  966.                      implements Set {
  967.     SynchronizedSet(Set s) {
  968.             super(s);
  969.         }
  970.     SynchronizedSet(Set s, Object mutex) {
  971.             super(s, mutex);
  972.         }
  973.  
  974.     public boolean equals(Object o) {
  975.         synchronized(mutex) {return c.equals(o);}
  976.         }
  977.     public int hashCode() {
  978.         synchronized(mutex) {return c.hashCode();}
  979.         }
  980.     }
  981.  
  982.     /**
  983.      * Returns a synchronized (thread-safe) SortedSet backed by the specified
  984.      * SortedSet. In order to guarantee serial access, it is critical that
  985.      * <strong>all</strong> access to the backing SortedSet is accomplished
  986.      * through the returned SortedSet (or its views).
  987.      * <p>
  988.      * It is imperative that the user manually synchronize on the returned
  989.      * SortedSet when iterating over it or any of its subSet, headSet, or
  990.      * tailSet views.
  991.      * <pre>
  992.      *  SortedSet s = synchronizedSortedSet(new HashSortedSet());
  993.      *      ...
  994.      *  synchronized(s) {
  995.      *      Iterator i = s.iterator(); // Must be in the synchronized block
  996.      *      while (i.hasNext())
  997.      *          foo(i.next();
  998.      *  }
  999.      * </pre>
  1000.      * or:
  1001.      * <pre>
  1002.      *  SortedSet s = synchronizedSortedSet(new HashSortedSet());
  1003.      *  SortedSet s2 = s.headSet(foo);
  1004.      *      ...
  1005.      *  synchronized(s) {  // Note: s, not s2!!!
  1006.      *      Iterator i = s2.iterator(); // Must be in the synchronized block
  1007.      *      while (i.hasNext())
  1008.      *          foo(i.next();
  1009.      *  }
  1010.      * </pre>
  1011.      * Failure to follow this advice may result in non-deterministic behavior.
  1012.      * <p>
  1013.      * The returned SortedSet will be Serializable if the specified SortedSet
  1014.      * is Serializable.
  1015.      *
  1016.      * @param s the SortedSet to be "wrapped" in a synchronized SortedSet.
  1017.      */
  1018.     public static SortedSet synchronizedSortedSet(SortedSet s) {
  1019.     return new SynchronizedSortedSet(s);
  1020.     }
  1021.  
  1022.     static class SynchronizedSortedSet extends SynchronizedSet
  1023.                      implements SortedSet
  1024.     {
  1025.         private SortedSet ss;
  1026.  
  1027.     SynchronizedSortedSet(SortedSet s) {
  1028.             super(s);
  1029.             ss = s;
  1030.         }
  1031.     SynchronizedSortedSet(SortedSet s, Object mutex) {
  1032.             super(s, mutex);
  1033.             ss = s;
  1034.         }
  1035.  
  1036.     public Comparator comparator() {
  1037.         synchronized(mutex) {return ss.comparator();}
  1038.         }
  1039.  
  1040.         public SortedSet subSet(Object fromElement, Object toElement) {
  1041.         synchronized(mutex) {
  1042.                 return new SynchronizedSortedSet(
  1043.                     ss.subSet(fromElement, toElement), mutex);
  1044.             }
  1045.         }
  1046.         public SortedSet headSet(Object toElement) {
  1047.         synchronized(mutex) {
  1048.                 return new SynchronizedSortedSet(ss.headSet(toElement), mutex);
  1049.             }
  1050.         }
  1051.         public SortedSet tailSet(Object fromElement) {
  1052.         synchronized(mutex) {
  1053.                return new SynchronizedSortedSet(ss.tailSet(fromElement),mutex);
  1054.             }
  1055.         }
  1056.  
  1057.         public Object first() {
  1058.         synchronized(mutex) {return ss.first();}
  1059.         }
  1060.         public Object last() {
  1061.         synchronized(mutex) {return ss.last();}
  1062.         }
  1063.     }
  1064.  
  1065.     /**
  1066.      * Returns a synchronized (thread-safe) List backed by the specified
  1067.      * List. In order to guarantee serial access, it is critical that
  1068.      * <strong>all</strong> access to the backing List is accomplished
  1069.      * through the returned List.
  1070.      * <p>
  1071.      * It is imperative that the user manually synchronize on the returned
  1072.      * List when iterating over it:
  1073.      * <pre>
  1074.      *  List list = synchronizedList(new Arraylist());
  1075.      *      ...
  1076.      *  synchronized(list) {
  1077.      *      Iterator i = list.iterator(); // Must be in synchronized block
  1078.      *      while (i.hasNext())
  1079.      *          foo(i.next();
  1080.      *  }
  1081.      * </pre>
  1082.      * Failure to follow this advice may result in non-deterministic behavior.
  1083.      * <p>
  1084.      * The returned List will be Serializable if the specified List is
  1085.      * Serializable.
  1086.      *
  1087.      * @param list the List to be "wrapped" in a synchronized List.
  1088.      */
  1089.     public static List synchronizedList(List list) {
  1090.     return new SynchronizedList(list);
  1091.     }
  1092.  
  1093.     static class SynchronizedList extends SynchronizedCollection
  1094.                           implements List {
  1095.     private List list;
  1096.  
  1097.     SynchronizedList(List list) {
  1098.         super(list);
  1099.         this.list = list;
  1100.     }
  1101.  
  1102.     public boolean equals(Object o) {
  1103.         synchronized(mutex) {return list.equals(o);}
  1104.         }
  1105.     public int hashCode() {
  1106.         synchronized(mutex) {return list.hashCode();}
  1107.         }
  1108.  
  1109.     public Object get(int index) {
  1110.         synchronized(mutex) {return list.get(index);}
  1111.         }
  1112.     public Object set(int index, Object element) {
  1113.         synchronized(mutex) {return list.set(index, element);}
  1114.         }
  1115.     public void add(int index, Object element) {
  1116.         synchronized(mutex) {list.add(index, element);}
  1117.         }
  1118.     public Object remove(int index) {
  1119.         synchronized(mutex) {return list.remove(index);}
  1120.         }
  1121.  
  1122.     public int indexOf(Object o) {
  1123.         synchronized(mutex) {return list.indexOf(o);}
  1124.         }
  1125.     public int indexOf(Object o, int i) {
  1126.         synchronized(mutex) {return list.indexOf(o, i);}
  1127.         }
  1128.     public int lastIndexOf(Object o) {
  1129.         synchronized(mutex) {return list.lastIndexOf(o);}
  1130.         }
  1131.     public int lastIndexOf(Object o, int i) {
  1132.         synchronized(mutex) {return list.lastIndexOf(o,i);}
  1133.         }
  1134.  
  1135.     public void removeRange(int fromIndex, int toIndex) {
  1136.         synchronized(mutex) {list.removeRange(fromIndex, toIndex);}
  1137.         }
  1138.     public boolean addAll(int index, Collection c) {
  1139.         synchronized(mutex) {return list.addAll(index, c);}
  1140.         }
  1141.  
  1142.     public ListIterator listIterator() {
  1143.         return list.listIterator(); // Must be manually synched by user
  1144.         }
  1145.  
  1146.     public ListIterator listIterator(int index) {
  1147.         return list.listIterator(index); // Must be manually synched by usr
  1148.         }
  1149.     }
  1150.  
  1151.     /**
  1152.      * Returns a synchronized (thread-safe) Map backed by the specified
  1153.      * Map. In order to guarantee serial access, it is critical that
  1154.      * <strong>all</strong> access to the backing Map is accomplished
  1155.      * through the returned Map.
  1156.      * <p>
  1157.      * It is imperative that the user manually synchronize on the returned
  1158.      * Map when iterating over any of its Collection views:
  1159.      * <pre>
  1160.      *  Map m = synchronizedMap(new HashMap());
  1161.      *      ...
  1162.      *  Set s = m.keySet();  // Needn't be in synchronized block
  1163.      *      ...
  1164.      *  synchronized(m) {  // Synchronizing on m, not s!
  1165.      *      Iterator i = s.iterator(); // Must be in synchronized block
  1166.      *      while (i.hasNext())
  1167.      *          foo(i.next();
  1168.      *  }
  1169.      * </pre>
  1170.      * Failure to follow this advice may result in non-deterministic behavior.
  1171.      * <p>
  1172.      * The returned Map will be Serializable if the specified Map is
  1173.      * Serializable.
  1174.      *
  1175.      * @param m the Map to be "wrapped" in a synchronized Map.
  1176.      */
  1177.     public static Map synchronizedMap(Map m) {
  1178.     return new SynchronizedMap(m);
  1179.     }
  1180.  
  1181.     private static class SynchronizedMap implements Map {
  1182.     private Map    m;    // Backing Map
  1183.         private Object mutex;    // Object on which to synchronize
  1184.  
  1185.     SynchronizedMap(Map m) {
  1186.             this.m = m;     mutex = this;
  1187.         }
  1188.  
  1189.     SynchronizedMap(Map m, Object mutex) {
  1190.             this.m = m;     this.mutex = mutex;
  1191.         }
  1192.  
  1193.     public int size() {
  1194.         synchronized(mutex) {return m.size();}
  1195.         }
  1196.     public boolean isEmpty(){
  1197.         synchronized(mutex) {return m.isEmpty();}
  1198.         }
  1199.     public boolean containsKey(Object key) {
  1200.         synchronized(mutex) {return m.containsKey(key);}
  1201.         }
  1202.     public boolean containsValue(Object value){
  1203.         synchronized(mutex) {return m.containsValue(value);}
  1204.         }
  1205.     public Object get(Object key) {
  1206.         synchronized(mutex) {return m.get(key);}
  1207.         }
  1208.  
  1209.     public Object put(Object key, Object value) {
  1210.         synchronized(mutex) {return m.put(key, value);}
  1211.         }
  1212.     public Object remove(Object key) {
  1213.         synchronized(mutex) {return m.remove(key);}
  1214.         }
  1215.     public void putAll(Map map) {
  1216.         synchronized(mutex) {m.putAll(map);}
  1217.         }
  1218.     public void clear() {
  1219.         synchronized(mutex) {m.clear();}
  1220.         }
  1221.  
  1222.     private transient Set keySet = null;
  1223.     private transient Set entries = null;
  1224.     private transient Collection values = null;
  1225.  
  1226.     public Set keySet() {
  1227.             synchronized(mutex) {
  1228.                 if (keySet==null)
  1229.                     keySet = new SynchronizedSet(m.keySet(), this);
  1230.                 return keySet;
  1231.             }
  1232.     }
  1233.  
  1234.     public Set entries() {
  1235.             synchronized(mutex) {
  1236.                 if (entries==null)
  1237.                     entries = new SynchronizedSet(m.entries(), this);
  1238.                 return entries;
  1239.             }
  1240.     }
  1241.  
  1242.     public Collection values() {
  1243.             synchronized(mutex) {
  1244.                 if (values==null)
  1245.                     values = new SynchronizedCollection(m.values(), this);
  1246.                 return values;
  1247.             }
  1248.         }
  1249.  
  1250.     public boolean equals(Object o) {
  1251.             synchronized(mutex) {return m.equals(o);}
  1252.         }
  1253.     public int hashCode() {
  1254.             synchronized(mutex) {return m.hashCode();}
  1255.         }
  1256.     }
  1257.  
  1258.     /**
  1259.      * Returns a synchronized (thread-safe) SortedMap backed by the specified
  1260.      * SortedMap. In order to guarantee serial access, it is critical that
  1261.      * <strong>all</strong> access to the backing SortedMap is accomplished
  1262.      * through the returned SortedMap (or its views).
  1263.      * <p>
  1264.      * It is imperative that the user manually synchronize on the returned
  1265.      * SortedMap when iterating over any of its Collection views, or the
  1266.      * Collections views of any of its subMap, headMap or tailMap views.
  1267.      * <pre>
  1268.      *  SortedMap m = synchronizedSortedMap(new HashSortedMap());
  1269.      *      ...
  1270.      *  Set s = m.keySet();  // Needn't be in synchronized block
  1271.      *      ...
  1272.      *  synchronized(m) {  // Synchronizing on m, not s!
  1273.      *      Iterator i = s.iterator(); // Must be in synchronized block
  1274.      *      while (i.hasNext())
  1275.      *          foo(i.next();
  1276.      *  }
  1277.      * </pre>
  1278.      * or:
  1279.      * <pre>
  1280.      *  SortedMap m = synchronizedSortedMap(new HashSortedMap());
  1281.      *  SortedMap m2 = m.subMap(foo, bar);
  1282.      *      ...
  1283.      *  Set s2 = m2.keySet();  // Needn't be in synchronized block
  1284.      *      ...
  1285.      *  synchronized(m) {  // Synchronizing on m, not m2 or s2!
  1286.      *      Iterator i = s.iterator(); // Must be in synchronized block
  1287.      *      while (i.hasNext())
  1288.      *          foo(i.next();
  1289.      *  }
  1290.      * </pre>
  1291.      * Failure to follow this advice may result in non-deterministic behavior.
  1292.      * <p>
  1293.      * The returned SortedMap will be Serializable if the specified SortedMap
  1294.      * is  Serializable.
  1295.      *
  1296.      * @param m the SortedMap to be "wrapped" in a synchronized SortedMap.
  1297.      */
  1298.     public static SortedMap synchronizedSortedMap(SortedMap m) {
  1299.     return new SynchronizedSortedMap(m);
  1300.     }
  1301.  
  1302.  
  1303.     static class SynchronizedSortedMap extends SynchronizedMap
  1304.                      implements SortedMap
  1305.     {
  1306.         private SortedMap sm;
  1307.  
  1308.     SynchronizedSortedMap(SortedMap m) {
  1309.             super(m);
  1310.             sm = m;
  1311.         }
  1312.     SynchronizedSortedMap(SortedMap m, Object mutex) {
  1313.             super(m, mutex);
  1314.             sm = m;
  1315.         }
  1316.  
  1317.     public Comparator comparator() {
  1318.         synchronized(mutex) {return sm.comparator();}
  1319.         }
  1320.  
  1321.         public SortedMap subMap(Object fromKey, Object toKey) {
  1322.         synchronized(mutex) {
  1323.                 return new SynchronizedSortedMap(
  1324.                     sm.subMap(fromKey, toKey), mutex);
  1325.             }
  1326.         }
  1327.         public SortedMap headMap(Object toKey) {
  1328.         synchronized(mutex) {
  1329.                 return new SynchronizedSortedMap(sm.headMap(toKey), mutex);
  1330.             }
  1331.         }
  1332.         public SortedMap tailMap(Object fromKey) {
  1333.         synchronized(mutex) {
  1334.                return new SynchronizedSortedMap(sm.tailMap(fromKey),mutex);
  1335.             }
  1336.         }
  1337.  
  1338.         public Object firstKey() {
  1339.         synchronized(mutex) {return sm.firstKey();}
  1340.         }
  1341.         public Object lastKey() {
  1342.         synchronized(mutex) {return sm.lastKey();}
  1343.         }
  1344.     }
  1345.  
  1346.     // Miscellaneous
  1347.  
  1348.     /**
  1349.      * Returns an immutable List consisting of n copies of the specified
  1350.      * Object.  The newly allocated data Object is tiny (it contains a single
  1351.      * reference to the data Object).  This method is useful in combination
  1352.      * with List.addAll to grow Lists.
  1353.      *
  1354.      * @param n the number of elements in the returned List.
  1355.      * @param o the element to appear repeatedly in the returned List.
  1356.      * @exception IllegalArgumentException n < 0.
  1357.      * @see List#addAll(Collection)
  1358.      * @see List#addAll(int, Collection)
  1359.      */
  1360.     public static List nCopies(final int n, final Object o) {
  1361.     if (n < 0)
  1362.         throw new IllegalArgumentException("List length = " + n);
  1363.  
  1364.     return new AbstractList() {
  1365.         public int size() {
  1366.         return n;
  1367.         }
  1368.  
  1369.         public boolean contains(Object obj) {
  1370.         return n!=0 && o.equals(obj);
  1371.         }
  1372.  
  1373.         public Object get(int index) {
  1374.         if (index<0 || index>n)
  1375.             throw new IndexOutOfBoundsException("Index: "+index+
  1376.                             ",Size: "+n);
  1377.         return o;
  1378.         }
  1379.         };
  1380.     }
  1381.  
  1382.     /**
  1383.      * A Comparator that imposes the reverse of the <em>natural ordering</em>
  1384.      * on a collection of Comparable objects.  (The natural ordering is the
  1385.      * ordering imposed by the objects' own compareTo method.)  This
  1386.      * enables a simple idiom for sorting (or maintaining) collections
  1387.      * (or arrays) of Comparable objects in reverse-natural-order.  For
  1388.      * example, suppose a is an array of String. Then: <pre>
  1389.      *         Arrays.sort(a, Collections.REVERSE_ORDER);
  1390.      * </pre> sorts the array in reverse-lexicographic (alphabetical) order.
  1391.      * <p>
  1392.      * This Comparator is Serializable.
  1393.      */
  1394.     public static final Comparator REVERSE_ORDER = new ReverseComparator();
  1395.  
  1396.     private static class ReverseComparator implements Comparator,Serializable {
  1397.         public int compare(Object o1, Object o2) {
  1398.             Comparable c1 = (Comparable)o1;
  1399.             Comparable c2 = (Comparable)o2;
  1400.             return -c1.compareTo(c2);
  1401.         }
  1402.     }
  1403.  
  1404.     /**
  1405.      * Returns an Enumeration over the specified Collection.  This provides
  1406.      * interoperatbility with legacy APIs that require an Enumeration
  1407.      * as input.
  1408.      *
  1409.      * @param c the Collection for which an Enumeration is to be returned.
  1410.      */
  1411.     public static Enumeration enumeration(final Collection c) {
  1412.     return new Enumeration() {
  1413.         Iterator i = c.iterator();
  1414.  
  1415.         public boolean hasMoreElements() {
  1416.         return i.hasNext();
  1417.         }
  1418.  
  1419.         public Object nextElement() {
  1420.         return i.next();
  1421.         }
  1422.         };
  1423.     }
  1424. }
  1425.