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

Comparing jsr166/src/main/java/util/Collections.java (file contents):
Revision 1.20 by jsr166, Wed Jan 11 00:57:12 2006 UTC vs.
Revision 1.32 by jsr166, Tue Sep 11 15:18:34 2007 UTC

# Line 1 | Line 1
1   /*
2 < * %W% %E%
2 > * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
3 > * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4   *
5 < * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
6 < * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
5 > * This code is free software; you can redistribute it and/or modify it
6 > * under the terms of the GNU General Public License version 2 only, as
7 > * published by the Free Software Foundation.  Sun designates this
8 > * particular file as subject to the "Classpath" exception as provided
9 > * by Sun in the LICENSE file that accompanied this code.
10 > *
11 > * This code is distributed in the hope that it will be useful, but WITHOUT
12 > * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 > * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 > * version 2 for more details (a copy is included in the LICENSE file that
15 > * accompanied this code).
16 > *
17 > * You should have received a copy of the GNU General Public License version
18 > * 2 along with this work; if not, write to the Free Software Foundation,
19 > * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 > *
21 > * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 > * CA 95054 USA or visit www.sun.com if you need additional information or
23 > * have any questions.
24   */
25  
26   package java.util;
9 import java.util.*; // for javadoc (till 6280605 is fixed)
27   import java.io.Serializable;
28   import java.io.ObjectOutputStream;
29   import java.io.IOException;
# Line 39 | Line 56 | import java.lang.reflect.Array;
56   * already sorted may or may not throw <tt>UnsupportedOperationException</tt>.
57   *
58   * <p>This class is a member of the
59 < * <a href="{@docRoot}/../guide/collections/index.html">
59 > * <a href="{@docRoot}/../technotes/guides/collections/index.html">
60   * Java Collections Framework</a>.
61   *
62   * @author  Josh Bloch
# Line 169 | Line 186 | public class Collections {
186      /**
187       * Searches the specified list for the specified object using the binary
188       * search algorithm.  The list must be sorted into ascending order
189 <     * according to the <i>natural ordering</i> of its elements (as by the
190 <     * <tt>sort(List)</tt> method, above) prior to making this call.  If it is
191 <     * not sorted, the results are undefined.  If the list contains multiple
192 <     * elements equal to the specified object, there is no guarantee which one
193 <     * will be found.<p>
189 >     * according to the {@linkplain Comparable natural ordering} of its
190 >     * elements (as by the {@link #sort(List)} method) prior to making this
191 >     * call.  If it is not sorted, the results are undefined.  If the list
192 >     * contains multiple elements equal to the specified object, there is no
193 >     * guarantee which one will be found.
194       *
195 <     * This method runs in log(n) time for a "random access" list (which
195 >     * <p>This method runs in log(n) time for a "random access" list (which
196       * provides near-constant-time positional access).  If the specified list
197       * does not implement the {@link RandomAccess} interface and is large,
198       * this method will do an iterator-based binary search that performs
# Line 187 | Line 204 | public class Collections {
204       *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
205       *         <i>insertion point</i> is defined as the point at which the
206       *         key would be inserted into the list: the index of the first
207 <     *         element greater than the key, or <tt>list.size()</tt>, if all
207 >     *         element greater than the key, or <tt>list.size()</tt> if all
208       *         elements in the list are less than the specified key.  Note
209       *         that this guarantees that the return value will be &gt;= 0 if
210       *         and only if the key is found.
211       * @throws ClassCastException if the list contains elements that are not
212       *         <i>mutually comparable</i> (for example, strings and
213 <     *         integers), or the search key in not mutually comparable
213 >     *         integers), or the search key is not mutually comparable
214       *         with the elements of the list.
198     * @see    Comparable
199     * @see #sort(List)
215       */
216      public static <T>
217      int binarySearch(List<? extends Comparable<? super T>> list, T key) {
# Line 213 | Line 228 | public class Collections {
228          int high = list.size()-1;
229  
230          while (low <= high) {
231 <            int mid = (low + high) >> 1;
231 >            int mid = (low + high) >>> 1;
232              Comparable<? super T> midVal = list.get(mid);
233              int cmp = midVal.compareTo(key);
234  
# Line 235 | Line 250 | public class Collections {
250          ListIterator<? extends Comparable<? super T>> i = list.listIterator();
251  
252          while (low <= high) {
253 <            int mid = (low + high) >> 1;
253 >            int mid = (low + high) >>> 1;
254              Comparable<? super T> midVal = get(i, mid);
255              int cmp = midVal.compareTo(key);
256  
# Line 271 | Line 286 | public class Collections {
286      /**
287       * Searches the specified list for the specified object using the binary
288       * search algorithm.  The list must be sorted into ascending order
289 <     * according to the specified comparator (as by the <tt>Sort(List,
290 <     * Comparator)</tt> method, above), prior to making this call.  If it is
289 >     * according to the specified comparator (as by the
290 >     * {@link #sort(List, Comparator) sort(List, Comparator)}
291 >     * method), prior to making this call.  If it is
292       * not sorted, the results are undefined.  If the list contains multiple
293       * elements equal to the specified object, there is no guarantee which one
294 <     * will be found.<p>
294 >     * will be found.
295       *
296 <     * This method runs in log(n) time for a "random access" list (which
296 >     * <p>This method runs in log(n) time for a "random access" list (which
297       * provides near-constant-time positional access).  If the specified list
298       * does not implement the {@link RandomAccess} interface and is large,
299       * this method will do an iterator-based binary search that performs
# Line 285 | Line 301 | public class Collections {
301       *
302       * @param  list the list to be searched.
303       * @param  key the key to be searched for.
304 <     * @param  c the comparator by which the list is ordered.  A
305 <     *        <tt>null</tt> value indicates that the elements' <i>natural
306 <     *        ordering</i> should be used.
304 >     * @param  c the comparator by which the list is ordered.
305 >     *         A <tt>null</tt> value indicates that the elements'
306 >     *         {@linkplain Comparable natural ordering} should be used.
307       * @return the index of the search key, if it is contained in the list;
308       *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
309       *         <i>insertion point</i> is defined as the point at which the
310       *         key would be inserted into the list: the index of the first
311 <     *         element greater than the key, or <tt>list.size()</tt>, if all
311 >     *         element greater than the key, or <tt>list.size()</tt> if all
312       *         elements in the list are less than the specified key.  Note
313       *         that this guarantees that the return value will be &gt;= 0 if
314       *         and only if the key is found.
315       * @throws ClassCastException if the list contains elements that are not
316       *         <i>mutually comparable</i> using the specified comparator,
317 <     *         or the search key in not mutually comparable with the
317 >     *         or the search key is not mutually comparable with the
318       *         elements of the list using this comparator.
303     * @see    Comparable
304     * @see #sort(List, Comparator)
319       */
320      public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c) {
321          if (c==null)
# Line 318 | Line 332 | public class Collections {
332          int high = l.size()-1;
333  
334          while (low <= high) {
335 <            int mid = (low + high) >> 1;
335 >            int mid = (low + high) >>> 1;
336              T midVal = l.get(mid);
337              int cmp = c.compare(midVal, key);
338  
# Line 338 | Line 352 | public class Collections {
352          ListIterator<? extends T> i = l.listIterator();
353  
354          while (low <= high) {
355 <            int mid = (low + high) >> 1;
355 >            int mid = (low + high) >>> 1;
356              T midVal = get(i, mid);
357              int cmp = c.compare(midVal, key);
358  
# Line 745 | Line 759 | public class Collections {
759       */
760      public static void rotate(List<?> list, int distance) {
761          if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD)
762 <            rotate1((List)list, distance);
762 >            rotate1(list, distance);
763          else
764 <            rotate2((List)list, distance);
764 >            rotate2(list, distance);
765      }
766  
767      private static <T> void rotate1(List<T> list, int distance) {
# Line 988 | Line 1002 | public class Collections {
1002       * @serial include
1003       */
1004      static class UnmodifiableCollection<E> implements Collection<E>, Serializable {
991        // use serialVersionUID from JDK 1.2.2 for interoperability
1005          private static final long serialVersionUID = 1820017752578914078L;
1006  
1007          final Collection<? extends E> c;
# Line 1008 | Line 1021 | public class Collections {
1021  
1022          public Iterator<E> iterator() {
1023              return new Iterator<E>() {
1024 <                Iterator<? extends E> i = c.iterator();
1024 >                private final Iterator<? extends E> i = c.iterator();
1025  
1026                  public boolean hasNext() {return i.hasNext();}
1027                  public E next()          {return i.next();}
# Line 1018 | Line 1031 | public class Collections {
1031              };
1032          }
1033  
1034 <        public boolean add(E e){
1034 >        public boolean add(E e) {
1035              throw new UnsupportedOperationException();
1036          }
1037          public boolean remove(Object o) {
# Line 1067 | Line 1080 | public class Collections {
1080          private static final long serialVersionUID = -9215047833775013803L;
1081  
1082          UnmodifiableSet(Set<? extends E> s)     {super(s);}
1083 <        public boolean equals(Object o) {return c.equals(o);}
1083 >        public boolean equals(Object o) {return o == this || c.equals(o);}
1084          public int hashCode()           {return c.hashCode();}
1085      }
1086  
# Line 1144 | Line 1157 | public class Collections {
1157       */
1158      static class UnmodifiableList<E> extends UnmodifiableCollection<E>
1159                                    implements List<E> {
1160 <        static final long serialVersionUID = -283967356065247728L;
1160 >        private static final long serialVersionUID = -283967356065247728L;
1161          final List<? extends E> list;
1162  
1163          UnmodifiableList(List<? extends E> list) {
# Line 1152 | Line 1165 | public class Collections {
1165              this.list = list;
1166          }
1167  
1168 <        public boolean equals(Object o) {return list.equals(o);}
1168 >        public boolean equals(Object o) {return o == this || list.equals(o);}
1169          public int hashCode()           {return list.hashCode();}
1170  
1171          public E get(int index) {return list.get(index);}
# Line 1174 | Line 1187 | public class Collections {
1187  
1188          public ListIterator<E> listIterator(final int index) {
1189              return new ListIterator<E>() {
1190 <                ListIterator<? extends E> i = list.listIterator(index);
1190 >                private final ListIterator<? extends E> i
1191 >                    = list.listIterator(index);
1192  
1193                  public boolean hasNext()     {return i.hasNext();}
1194                  public E next()              {return i.next();}
# Line 1268 | Line 1282 | public class Collections {
1282       * @serial include
1283       */
1284      private static class UnmodifiableMap<K,V> implements Map<K,V>, Serializable {
1271        // use serialVersionUID from JDK 1.2.2 for interoperability
1285          private static final long serialVersionUID = -1034234728574286014L;
1286  
1287          private final Map<? extends K, ? extends V> m;
# Line 1320 | Line 1333 | public class Collections {
1333              return values;
1334          }
1335  
1336 <        public boolean equals(Object o) {return m.equals(o);}
1336 >        public boolean equals(Object o) {return o == this || m.equals(o);}
1337          public int hashCode()           {return m.hashCode();}
1338          public String toString()        {return m.toString();}
1339  
# Line 1341 | Line 1354 | public class Collections {
1354              }
1355              public Iterator<Map.Entry<K,V>> iterator() {
1356                  return new Iterator<Map.Entry<K,V>>() {
1357 <                    Iterator<? extends Map.Entry<? extends K, ? extends V>> i = c.iterator();
1357 >                    private final Iterator<? extends Map.Entry<? extends K, ? extends V>> i = c.iterator();
1358  
1359                      public boolean hasNext() {
1360                          return i.hasNext();
# Line 1389 | Line 1402 | public class Collections {
1402              public boolean contains(Object o) {
1403                  if (!(o instanceof Map.Entry))
1404                      return false;
1405 <                return c.contains(new UnmodifiableEntry<K,V>((Map.Entry<K,V>) o));
1405 >                return c.contains(
1406 >                    new UnmodifiableEntry<Object,Object>((Map.Entry<?,?>) o));
1407              }
1408  
1409              /**
# Line 1540 | Line 1554 | public class Collections {
1554       * @serial include
1555       */
1556      static class SynchronizedCollection<E> implements Collection<E>, Serializable {
1543        // use serialVersionUID from JDK 1.2.2 for interoperability
1557          private static final long serialVersionUID = 3053995032091335093L;
1558  
1559 <        final Collection<E> c;     // Backing Collection
1560 <        final Object       mutex;  // Object on which to synchronize
1559 >        final Collection<E> c;  // Backing Collection
1560 >        final Object mutex;     // Object on which to synchronize
1561  
1562          SynchronizedCollection(Collection<E> c) {
1563              if (c==null)
# Line 1796 | Line 1809 | public class Collections {
1809      static class SynchronizedList<E>
1810          extends SynchronizedCollection<E>
1811          implements List<E> {
1812 <        static final long serialVersionUID = -7754090372962971524L;
1812 >        private static final long serialVersionUID = -7754090372962971524L;
1813  
1814          final List<E> list;
1815  
# Line 1896 | Line 1909 | public class Collections {
1909              }
1910          }
1911  
1912 <        static final long serialVersionUID = 1530674583602358482L;
1912 >        private static final long serialVersionUID = 1530674583602358482L;
1913  
1914          /**
1915           * Allows instances to be deserialized in pre-1.4 JREs (which do
# Line 1945 | Line 1958 | public class Collections {
1958       */
1959      private static class SynchronizedMap<K,V>
1960          implements Map<K,V>, Serializable {
1948        // use serialVersionUID from JDK 1.2.2 for interoperability
1961          private static final long serialVersionUID = 1978198479659022715L;
1962  
1963          private final Map<K,V> m;     // Backing Map
# Line 1966 | Line 1978 | public class Collections {
1978          public int size() {
1979              synchronized(mutex) {return m.size();}
1980          }
1981 <        public boolean isEmpty(){
1981 >        public boolean isEmpty() {
1982              synchronized(mutex) {return m.isEmpty();}
1983          }
1984          public boolean containsKey(Object key) {
1985              synchronized(mutex) {return m.containsKey(key);}
1986          }
1987 <        public boolean containsValue(Object value){
1987 >        public boolean containsValue(Object value) {
1988              synchronized(mutex) {return m.containsValue(value);}
1989          }
1990          public V get(Object key) {
# Line 2133 | Line 2145 | public class Collections {
2145      // Dynamically typesafe collection wrappers
2146  
2147      /**
2148 <     * Returns a dynamically typesafe view of the specified collection.  Any
2149 <     * attempt to insert an element of the wrong type will result in an
2150 <     * immediate <tt>ClassCastException</tt>.  Assuming a collection contains
2151 <     * no incorrectly typed elements prior to the time a dynamically typesafe
2152 <     * view is generated, and that all subsequent access to the collection
2153 <     * takes place through the view, it is <i>guaranteed</i> that the
2154 <     * collection cannot contain an incorrectly typed element.
2148 >     * Returns a dynamically typesafe view of the specified collection.
2149 >     * Any attempt to insert an element of the wrong type will result in an
2150 >     * immediate {@link ClassCastException}.  Assuming a collection
2151 >     * contains no incorrectly typed elements prior to the time a
2152 >     * dynamically typesafe view is generated, and that all subsequent
2153 >     * access to the collection takes place through the view, it is
2154 >     * <i>guaranteed</i> that the collection cannot contain an incorrectly
2155 >     * typed element.
2156       *
2157       * <p>The generics mechanism in the language provides compile-time
2158       * (static) type checking, but it is possible to defeat this mechanism
# Line 2151 | Line 2164 | public class Collections {
2164       * inserting an element of the wrong type.
2165       *
2166       * <p>Another use of dynamically typesafe views is debugging.  Suppose a
2167 <     * program fails with a <tt>ClassCastException</tt>, indicating that an
2167 >     * program fails with a {@code ClassCastException}, indicating that an
2168       * incorrectly typed element was put into a parameterized collection.
2169       * Unfortunately, the exception can occur at any time after the erroneous
2170       * element is inserted, so it typically provides little or no information
# Line 2159 | Line 2172 | public class Collections {
2172       * one can quickly determine its source by temporarily modifying the
2173       * program to wrap the collection with a dynamically typesafe view.
2174       * For example, this declaration:
2175 <     * <pre>
2176 <     *     Collection&lt;String&gt; c = new HashSet&lt;String&gt;();
2177 <     * </pre>
2175 >     *  <pre> {@code
2176 >     *     Collection<String> c = new HashSet<String>();
2177 >     * }</pre>
2178       * may be replaced temporarily by this one:
2179 <     * <pre>
2180 <     *     Collection&lt;String&gt; c = Collections.checkedCollection(
2181 <     *         new HashSet&lt;String&gt;(), String.class);
2182 <     * </pre>
2179 >     *  <pre> {@code
2180 >     *     Collection<String> c = Collections.checkedCollection(
2181 >     *         new HashSet<String>(), String.class);
2182 >     * }</pre>
2183       * Running the program again will cause it to fail at the point where
2184       * an incorrectly typed element is inserted into the collection, clearly
2185       * identifying the source of the problem.  Once the problem is fixed, the
# Line 2174 | Line 2187 | public class Collections {
2187       *
2188       * <p>The returned collection does <i>not</i> pass the hashCode and equals
2189       * operations through to the backing collection, but relies on
2190 <     * <tt>Object</tt>'s <tt>equals</tt> and <tt>hashCode</tt> methods.  This
2190 >     * {@code Object}'s {@code equals} and {@code hashCode} methods.  This
2191       * is necessary to preserve the contracts of these operations in the case
2192       * that the backing collection is a set or a list.
2193       *
2194       * <p>The returned collection will be serializable if the specified
2195       * collection is serializable.
2196       *
2197 +     * <p>Since {@code null} is considered to be a value of any reference
2198 +     * type, the returned collection permits insertion of null elements
2199 +     * whenever the backing collection does.
2200 +     *
2201       * @param c the collection for which a dynamically typesafe view is to be
2202 <     *             returned
2203 <     * @param type the type of element that <tt>c</tt> is permitted to hold
2202 >     *          returned
2203 >     * @param type the type of element that {@code c} is permitted to hold
2204       * @return a dynamically typesafe view of the specified collection
2205       * @since 1.5
2206       */
# Line 2192 | Line 2209 | public class Collections {
2209          return new CheckedCollection<E>(c, type);
2210      }
2211  
2212 +    @SuppressWarnings("unchecked")
2213 +    static <T> T[] zeroLengthArray(Class<T> type) {
2214 +        return (T[]) Array.newInstance(type, 0);
2215 +    }
2216 +
2217      /**
2218       * @serial include
2219       */
# Line 2202 | Line 2224 | public class Collections {
2224          final Class<E> type;
2225  
2226          void typeCheck(Object o) {
2227 <            if (!type.isInstance(o))
2228 <                throw new ClassCastException("Attempt to insert " +
2207 <                   o.getClass() + " element into collection with element type "
2208 <                   + type);
2227 >            if (o != null && !type.isInstance(o))
2228 >                throw new ClassCastException(badElementMsg(o));
2229          }
2230  
2231 +        private String badElementMsg(Object o) {
2232 +            return "Attempt to insert " + o.getClass() +
2233 +                " element into collection with element type " + type;
2234 +        }
2235 +
2236          CheckedCollection(Collection<E> c, Class<E> type) {
2237              if (c==null || type == null)
2238                  throw new NullPointerException();
# Line 2215 | Line 2240 | public class Collections {
2240              this.type = type;
2241          }
2242  
2243 <        public int size()                   { return c.size(); }
2244 <        public boolean isEmpty()            { return c.isEmpty(); }
2245 <        public boolean contains(Object o)   { return c.contains(o); }
2246 <        public Object[] toArray()           { return c.toArray(); }
2247 <        public <T> T[] toArray(T[] a)       { return c.toArray(a); }
2248 <        public String toString()            { return c.toString(); }
2249 <        public boolean remove(Object o)     { return c.remove(o); }
2250 <        public boolean containsAll(Collection<?> coll) {
2243 >        public int size()                 { return c.size(); }
2244 >        public boolean isEmpty()          { return c.isEmpty(); }
2245 >        public boolean contains(Object o) { return c.contains(o); }
2246 >        public Object[] toArray()         { return c.toArray(); }
2247 >        public <T> T[] toArray(T[] a)     { return c.toArray(a); }
2248 >        public String toString()          { return c.toString(); }
2249 >        public boolean remove(Object o)   { return c.remove(o); }
2250 >        public void clear()               {        c.clear(); }
2251 >
2252 >        public boolean containsAll(Collection<?> coll) {
2253              return c.containsAll(coll);
2254          }
2255          public boolean removeAll(Collection<?> coll) {
# Line 2231 | Line 2258 | public class Collections {
2258          public boolean retainAll(Collection<?> coll) {
2259              return c.retainAll(coll);
2260          }
2234        public void clear() {
2235            c.clear();
2236        }
2261  
2262          public Iterator<E> iterator() {
2263 +            final Iterator<E> it = c.iterator();
2264              return new Iterator<E>() {
2240                private final Iterator<E> it = c.iterator();
2265                  public boolean hasNext() { return it.hasNext(); }
2266                  public E next()          { return it.next(); }
2267                  public void remove()     {        it.remove(); }};
2268          }
2269  
2270 <        public boolean add(E e){
2270 >        public boolean add(E e) {
2271              typeCheck(e);
2272              return c.add(e);
2273          }
2274  
2251        public boolean addAll(Collection<? extends E> coll) {
2252            /*
2253             * Dump coll into an array of the required type.  This serves
2254             * three purposes: it insulates us from concurrent changes in
2255             * the contents of coll, it type-checks all of the elements in
2256             * coll, and it provides all-or-nothing semantics (which we
2257             * wouldn't get if we type-checked each element as we added it).
2258             */
2259            E[] a = null;
2260            try {
2261                a = coll.toArray(zeroLengthElementArray());
2262            } catch (ArrayStoreException e) {
2263                throw new ClassCastException();
2264            }
2265
2266            boolean result = false;
2267            for (E e : a)
2268                result |= c.add(e);
2269            return result;
2270        }
2271
2275          private E[] zeroLengthElementArray = null; // Lazily initialized
2276  
2277 <        /*
2278 <         * We don't need locking or volatile, because it's OK if we create
2279 <         * several zeroLengthElementArrays, and they're immutable.
2280 <         */
2281 <        E[] zeroLengthElementArray() {
2282 <            if (zeroLengthElementArray == null)
2283 <                zeroLengthElementArray = (E[]) Array.newInstance(type, 0);
2284 <            return zeroLengthElementArray;
2277 >        private E[] zeroLengthElementArray() {
2278 >            return zeroLengthElementArray != null ? zeroLengthElementArray :
2279 >                (zeroLengthElementArray = zeroLengthArray(type));
2280 >        }
2281 >
2282 >        @SuppressWarnings("unchecked")
2283 >        Collection<E> checkedCopyOf(Collection<? extends E> coll) {
2284 >            Object[] a = null;
2285 >            try {
2286 >                E[] z = zeroLengthElementArray();
2287 >                a = coll.toArray(z);
2288 >                // Defend against coll violating the toArray contract
2289 >                if (a.getClass() != z.getClass())
2290 >                    a = Arrays.copyOf(a, a.length, z.getClass());
2291 >            } catch (ArrayStoreException ignore) {
2292 >                // To get better and consistent diagnostics,
2293 >                // we call typeCheck explicitly on each element.
2294 >                // We call clone() to defend against coll retaining a
2295 >                // reference to the returned array and storing a bad
2296 >                // element into it after it has been type checked.
2297 >                a = coll.toArray().clone();
2298 >                for (Object o : a)
2299 >                    typeCheck(o);
2300 >            }
2301 >            // A slight abuse of the type system, but safe here.
2302 >            return (Collection<E>) Arrays.asList(a);
2303 >        }
2304 >
2305 >        public boolean addAll(Collection<? extends E> coll) {
2306 >            // Doing things this way insulates us from concurrent changes
2307 >            // in the contents of coll and provides all-or-nothing
2308 >            // semantics (which we wouldn't get if we type-checked each
2309 >            // element as we added it)
2310 >            return c.addAll(checkedCopyOf(coll));
2311          }
2312      }
2313  
2314      /**
2315       * Returns a dynamically typesafe view of the specified set.
2316       * Any attempt to insert an element of the wrong type will result in
2317 <     * an immediate <tt>ClassCastException</tt>.  Assuming a set contains
2317 >     * an immediate {@link ClassCastException}.  Assuming a set contains
2318       * no incorrectly typed elements prior to the time a dynamically typesafe
2319       * view is generated, and that all subsequent access to the set
2320       * takes place through the view, it is <i>guaranteed</i> that the
2321       * set cannot contain an incorrectly typed element.
2322       *
2323       * <p>A discussion of the use of dynamically typesafe views may be
2324 <     * found in the documentation for the {@link #checkedCollection checkedCollection}
2325 <     * method.
2324 >     * found in the documentation for the {@link #checkedCollection
2325 >     * checkedCollection} method.
2326       *
2327       * <p>The returned set will be serializable if the specified set is
2328       * serializable.
2329       *
2330 +     * <p>Since {@code null} is considered to be a value of any reference
2331 +     * type, the returned set permits insertion of null elements whenever
2332 +     * the backing set does.
2333 +     *
2334       * @param s the set for which a dynamically typesafe view is to be
2335 <     *             returned
2336 <     * @param type the type of element that <tt>s</tt> is permitted to hold
2335 >     *          returned
2336 >     * @param type the type of element that {@code s} is permitted to hold
2337       * @return a dynamically typesafe view of the specified set
2338       * @since 1.5
2339       */
# Line 2318 | Line 2351 | public class Collections {
2351  
2352          CheckedSet(Set<E> s, Class<E> elementType) { super(s, elementType); }
2353  
2354 <        public boolean equals(Object o) { return c.equals(o); }
2354 >        public boolean equals(Object o) { return o == this || c.equals(o); }
2355          public int hashCode()           { return c.hashCode(); }
2356      }
2357  
2358      /**
2359 <     * Returns a dynamically typesafe view of the specified sorted set.  Any
2360 <     * attempt to insert an element of the wrong type will result in an
2361 <     * immediate <tt>ClassCastException</tt>.  Assuming a sorted set contains
2362 <     * no incorrectly typed elements prior to the time a dynamically typesafe
2363 <     * view is generated, and that all subsequent access to the sorted set
2364 <     * takes place through the view, it is <i>guaranteed</i> that the sorted
2365 <     * set cannot contain an incorrectly typed element.
2359 >     * Returns a dynamically typesafe view of the specified sorted set.
2360 >     * Any attempt to insert an element of the wrong type will result in an
2361 >     * immediate {@link ClassCastException}.  Assuming a sorted set
2362 >     * contains no incorrectly typed elements prior to the time a
2363 >     * dynamically typesafe view is generated, and that all subsequent
2364 >     * access to the sorted set takes place through the view, it is
2365 >     * <i>guaranteed</i> that the sorted set cannot contain an incorrectly
2366 >     * typed element.
2367       *
2368       * <p>A discussion of the use of dynamically typesafe views may be
2369 <     * found in the documentation for the {@link #checkedCollection checkedCollection}
2370 <     * method.
2369 >     * found in the documentation for the {@link #checkedCollection
2370 >     * checkedCollection} method.
2371       *
2372       * <p>The returned sorted set will be serializable if the specified sorted
2373       * set is serializable.
2374       *
2375 +     * <p>Since {@code null} is considered to be a value of any reference
2376 +     * type, the returned sorted set permits insertion of null elements
2377 +     * whenever the backing sorted set does.
2378 +     *
2379       * @param s the sorted set for which a dynamically typesafe view is to be
2380 <     *             returned
2381 <     * @param type the type of element that <tt>s</tt> is permitted to hold
2380 >     *          returned
2381 >     * @param type the type of element that {@code s} is permitted to hold
2382       * @return a dynamically typesafe view of the specified sorted set
2383       * @since 1.5
2384       */
# Line 2368 | Line 2406 | public class Collections {
2406          public E last()                    { return ss.last(); }
2407  
2408          public SortedSet<E> subSet(E fromElement, E toElement) {
2409 <            return new CheckedSortedSet<E>(ss.subSet(fromElement,toElement),
2372 <                                           type);
2409 >            return checkedSortedSet(ss.subSet(fromElement,toElement), type);
2410          }
2411          public SortedSet<E> headSet(E toElement) {
2412 <            return new CheckedSortedSet<E>(ss.headSet(toElement), type);
2412 >            return checkedSortedSet(ss.headSet(toElement), type);
2413          }
2414          public SortedSet<E> tailSet(E fromElement) {
2415 <            return new CheckedSortedSet<E>(ss.tailSet(fromElement), type);
2415 >            return checkedSortedSet(ss.tailSet(fromElement), type);
2416          }
2417      }
2418  
2419      /**
2420       * Returns a dynamically typesafe view of the specified list.
2421       * Any attempt to insert an element of the wrong type will result in
2422 <     * an immediate <tt>ClassCastException</tt>.  Assuming a list contains
2422 >     * an immediate {@link ClassCastException}.  Assuming a list contains
2423       * no incorrectly typed elements prior to the time a dynamically typesafe
2424       * view is generated, and that all subsequent access to the list
2425       * takes place through the view, it is <i>guaranteed</i> that the
2426       * list cannot contain an incorrectly typed element.
2427       *
2428       * <p>A discussion of the use of dynamically typesafe views may be
2429 <     * found in the documentation for the {@link #checkedCollection checkedCollection}
2430 <     * method.
2429 >     * found in the documentation for the {@link #checkedCollection
2430 >     * checkedCollection} method.
2431       *
2432 <     * <p>The returned list will be serializable if the specified list is
2433 <     * serializable.
2432 >     * <p>The returned list will be serializable if the specified list
2433 >     * is serializable.
2434 >     *
2435 >     * <p>Since {@code null} is considered to be a value of any reference
2436 >     * type, the returned list permits insertion of null elements whenever
2437 >     * the backing list does.
2438       *
2439       * @param list the list for which a dynamically typesafe view is to be
2440       *             returned
2441 <     * @param type the type of element that <tt>list</tt> is permitted to hold
2441 >     * @param type the type of element that {@code list} is permitted to hold
2442       * @return a dynamically typesafe view of the specified list
2443       * @since 1.5
2444       */
# Line 2410 | Line 2451 | public class Collections {
2451      /**
2452       * @serial include
2453       */
2454 <    static class CheckedList<E> extends CheckedCollection<E>
2455 <                                implements List<E>
2454 >    static class CheckedList<E>
2455 >        extends CheckedCollection<E>
2456 >        implements List<E>
2457      {
2458 <        static final long serialVersionUID = 65247728283967356L;
2458 >        private static final long serialVersionUID = 65247728283967356L;
2459          final List<E> list;
2460  
2461          CheckedList(List<E> list, Class<E> type) {
# Line 2421 | Line 2463 | public class Collections {
2463              this.list = list;
2464          }
2465  
2466 <        public boolean equals(Object o)  { return list.equals(o); }
2466 >        public boolean equals(Object o)  { return o == this || list.equals(o); }
2467          public int hashCode()            { return list.hashCode(); }
2468          public E get(int index)          { return list.get(index); }
2469          public E remove(int index)       { return list.remove(index); }
# Line 2439 | Line 2481 | public class Collections {
2481          }
2482  
2483          public boolean addAll(int index, Collection<? extends E> c) {
2484 <            // See CheckCollection.addAll, above, for an explanation
2443 <            E[] a = null;
2444 <            try {
2445 <                a = c.toArray(zeroLengthElementArray());
2446 <            } catch (ArrayStoreException e) {
2447 <                throw new ClassCastException();
2448 <            }
2449 <
2450 <            return list.addAll(index, Arrays.asList(a));
2484 >            return list.addAll(index, checkedCopyOf(c));
2485          }
2486          public ListIterator<E> listIterator()   { return listIterator(0); }
2487  
2488          public ListIterator<E> listIterator(final int index) {
2489 <            return new ListIterator<E>() {
2456 <                ListIterator<E> i = list.listIterator(index);
2489 >            final ListIterator<E> i = list.listIterator(index);
2490  
2491 +            return new ListIterator<E>() {
2492                  public boolean hasNext()     { return i.hasNext(); }
2493                  public E next()              { return i.next(); }
2494                  public boolean hasPrevious() { return i.hasPrevious(); }
2495                  public E previous()          { return i.previous(); }
2496                  public int nextIndex()       { return i.nextIndex(); }
2497                  public int previousIndex()   { return i.previousIndex(); }
2498 <                public void remove()         { i.remove(); }
2498 >                public void remove()         {        i.remove(); }
2499  
2500                  public void set(E e) {
2501                      typeCheck(e);
# Line 2499 | Line 2533 | public class Collections {
2533      }
2534  
2535      /**
2536 <     * Returns a dynamically typesafe view of the specified map.  Any attempt
2537 <     * to insert a mapping whose key or value have the wrong type will result
2538 <     * in an immediate <tt>ClassCastException</tt>.  Similarly, any attempt to
2539 <     * modify the value currently associated with a key will result in an
2540 <     * immediate <tt>ClassCastException</tt>, whether the modification is
2541 <     * attempted directly through the map itself, or through a {@link
2542 <     * Map.Entry} instance obtained from the map's {@link Map#entrySet()
2543 <     * entry set} view.
2536 >     * Returns a dynamically typesafe view of the specified map.
2537 >     * Any attempt to insert a mapping whose key or value have the wrong
2538 >     * type will result in an immediate {@link ClassCastException}.
2539 >     * Similarly, any attempt to modify the value currently associated with
2540 >     * a key will result in an immediate {@link ClassCastException},
2541 >     * whether the modification is attempted directly through the map
2542 >     * itself, or through a {@link Map.Entry} instance obtained from the
2543 >     * map's {@link Map#entrySet() entry set} view.
2544       *
2545       * <p>Assuming a map contains no incorrectly typed keys or values
2546       * prior to the time a dynamically typesafe view is generated, and
# Line 2515 | Line 2549 | public class Collections {
2549       * map cannot contain an incorrectly typed key or value.
2550       *
2551       * <p>A discussion of the use of dynamically typesafe views may be
2552 <     * found in the documentation for the {@link #checkedCollection checkedCollection}
2553 <     * method.
2552 >     * found in the documentation for the {@link #checkedCollection
2553 >     * checkedCollection} method.
2554       *
2555       * <p>The returned map will be serializable if the specified map is
2556       * serializable.
2557       *
2558 +     * <p>Since {@code null} is considered to be a value of any reference
2559 +     * type, the returned map permits insertion of null keys or values
2560 +     * whenever the backing map does.
2561 +     *
2562       * @param m the map for which a dynamically typesafe view is to be
2563 <     *             returned
2564 <     * @param keyType the type of key that <tt>m</tt> is permitted to hold
2565 <     * @param valueType the type of value that <tt>m</tt> is permitted to hold
2563 >     *          returned
2564 >     * @param keyType the type of key that {@code m} is permitted to hold
2565 >     * @param valueType the type of value that {@code m} is permitted to hold
2566       * @return a dynamically typesafe view of the specified map
2567       * @since 1.5
2568       */
2569 <    public static <K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType,
2569 >    public static <K, V> Map<K, V> checkedMap(Map<K, V> m,
2570 >                                              Class<K> keyType,
2571                                                Class<V> valueType) {
2572          return new CheckedMap<K,V>(m, keyType, valueType);
2573      }
# Line 2537 | Line 2576 | public class Collections {
2576      /**
2577       * @serial include
2578       */
2579 <    private static class CheckedMap<K,V> implements Map<K,V>,
2580 <                                                         Serializable
2579 >    private static class CheckedMap<K,V>
2580 >        implements Map<K,V>, Serializable
2581      {
2582          private static final long serialVersionUID = 5742860141034234728L;
2583  
# Line 2547 | Line 2586 | public class Collections {
2586          final Class<V> valueType;
2587  
2588          private void typeCheck(Object key, Object value) {
2589 <            if (!keyType.isInstance(key))
2590 <                throw new ClassCastException("Attempt to insert " +
2591 <                    key.getClass() + " key into collection with key type "
2592 <                    + keyType);
2593 <
2555 <            if (!valueType.isInstance(value))
2556 <                throw new ClassCastException("Attempt to insert " +
2557 <                    value.getClass() +" value into collection with value type "
2558 <                    + valueType);
2589 >            if (key != null && !keyType.isInstance(key))
2590 >                throw new ClassCastException(badKeyMsg(key));
2591 >
2592 >            if (value != null && !valueType.isInstance(value))
2593 >                throw new ClassCastException(badValueMsg(value));
2594          }
2595  
2596 +        private String badKeyMsg(Object key) {
2597 +            return "Attempt to insert " + key.getClass() +
2598 +                " key into map with key type " + keyType;
2599 +        }
2600 +
2601 +        private String badValueMsg(Object value) {
2602 +            return "Attempt to insert " + value.getClass() +
2603 +                " value into map with value type " + valueType;
2604 +        }
2605 +
2606          CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {
2607              if (m == null || keyType == null || valueType == null)
2608                  throw new NullPointerException();
# Line 2575 | Line 2620 | public class Collections {
2620          public void clear()                    { m.clear(); }
2621          public Set<K> keySet()                 { return m.keySet(); }
2622          public Collection<V> values()          { return m.values(); }
2623 <        public boolean equals(Object o)        { return m.equals(o);  }
2623 >        public boolean equals(Object o)        { return o == this || m.equals(o); }
2624          public int hashCode()                  { return m.hashCode(); }
2625          public String toString()               { return m.toString(); }
2626  
# Line 2584 | Line 2629 | public class Collections {
2629              return m.put(key, value);
2630          }
2631  
2632 <        public void putAll(Map<? extends K, ? extends V> t) {
2633 <            // See CheckCollection.addAll, above, for an explanation
2634 <            K[] keys = null;
2635 <            try {
2636 <                keys = t.keySet().toArray(zeroLengthKeyArray());
2637 <            } catch (ArrayStoreException e) {
2638 <                throw new ClassCastException();
2639 <            }
2640 <            V[] values = null;
2641 <            try {
2642 <                values = t.values().toArray(zeroLengthValueArray());
2643 <            } catch (ArrayStoreException e) {
2644 <                throw new ClassCastException();
2645 <            }
2646 <
2647 <            if (keys.length != values.length)
2648 <                throw new ConcurrentModificationException();
2649 <
2650 <            for (int i = 0; i < keys.length; i++)
2651 <                m.put(keys[i], values[i]);
2652 <        }
2608 <
2609 <        // Lazily initialized
2610 <        private K[] zeroLengthKeyArray   = null;
2611 <        private V[] zeroLengthValueArray = null;
2612 <
2613 <        /*
2614 <         * We don't need locking or volatile, because it's OK if we create
2615 <         * several zeroLengthValueArrays, and they're immutable.
2616 <         */
2617 <        private K[] zeroLengthKeyArray() {
2618 <            if (zeroLengthKeyArray == null)
2619 <                zeroLengthKeyArray = (K[]) Array.newInstance(keyType, 0);
2620 <            return zeroLengthKeyArray;
2621 <        }
2622 <        private V[] zeroLengthValueArray() {
2623 <            if (zeroLengthValueArray == null)
2624 <                zeroLengthValueArray = (V[]) Array.newInstance(valueType, 0);
2625 <            return zeroLengthValueArray;
2626 <        }
2632 >        @SuppressWarnings("unchecked")
2633 >        public void putAll(Map<? extends K, ? extends V> t) {
2634 >            // Satisfy the following goals:
2635 >            // - good diagnostics in case of type mismatch
2636 >            // - all-or-nothing semantics
2637 >            // - protection from malicious t
2638 >            // - correct behavior if t is a concurrent map
2639 >            Object[] entries = t.entrySet().toArray();
2640 >            List<Map.Entry<K,V>> checked =
2641 >                new ArrayList<Map.Entry<K,V>>(entries.length);
2642 >            for (Object o : entries) {
2643 >                Map.Entry<?,?> e = (Map.Entry<?,?>) o;
2644 >                Object k = e.getKey();
2645 >                Object v = e.getValue();
2646 >                typeCheck(k, v);
2647 >                checked.add(
2648 >                    new AbstractMap.SimpleImmutableEntry<K,V>((K) k, (V) v));
2649 >            }
2650 >            for (Map.Entry<K,V> e : checked)
2651 >                m.put(e.getKey(), e.getValue());
2652 >        }
2653  
2654          private transient Set<Map.Entry<K,V>> entrySet = null;
2655  
# Line 2642 | Line 2668 | public class Collections {
2668           * @serial exclude
2669           */
2670          static class CheckedEntrySet<K,V> implements Set<Map.Entry<K,V>> {
2671 <            Set<Map.Entry<K,V>> s;
2672 <            Class<V> valueType;
2671 >            private final Set<Map.Entry<K,V>> s;
2672 >            private final Class<V> valueType;
2673  
2674              CheckedEntrySet(Set<Map.Entry<K, V>> s, Class<V> valueType) {
2675                  this.s = s;
2676                  this.valueType = valueType;
2677              }
2678  
2679 <            public int size()                   { return s.size(); }
2680 <            public boolean isEmpty()            { return s.isEmpty(); }
2681 <            public String toString()            { return s.toString(); }
2682 <            public int hashCode()               { return s.hashCode(); }
2683 <            public boolean remove(Object o)     { return s.remove(o); }
2658 <            public boolean removeAll(Collection<?> coll) {
2659 <                return s.removeAll(coll);
2660 <            }
2661 <            public boolean retainAll(Collection<?> coll) {
2662 <                return s.retainAll(coll);
2663 <            }
2664 <            public void clear() {
2665 <                s.clear();
2666 <            }
2679 >            public int size()        { return s.size(); }
2680 >            public boolean isEmpty() { return s.isEmpty(); }
2681 >            public String toString() { return s.toString(); }
2682 >            public int hashCode()    { return s.hashCode(); }
2683 >            public void clear()      {        s.clear(); }
2684  
2685 <            public boolean add(Map.Entry<K, V> e){
2685 >            public boolean add(Map.Entry<K, V> e) {
2686                  throw new UnsupportedOperationException();
2687              }
2688              public boolean addAll(Collection<? extends Map.Entry<K, V>> coll) {
2689                  throw new UnsupportedOperationException();
2690              }
2691  
2675
2692              public Iterator<Map.Entry<K,V>> iterator() {
2693 <                return new Iterator<Map.Entry<K,V>>() {
2694 <                    Iterator<Map.Entry<K, V>> i = s.iterator();
2693 >                final Iterator<Map.Entry<K, V>> i = s.iterator();
2694 >                final Class<V> valueType = this.valueType;
2695  
2696 +                return new Iterator<Map.Entry<K,V>>() {
2697                      public boolean hasNext() { return i.hasNext(); }
2698                      public void remove()     { i.remove(); }
2699  
2700                      public Map.Entry<K,V> next() {
2701 <                        return new CheckedEntry<K,V>(i.next(), valueType);
2701 >                        return checkedEntry(i.next(), valueType);
2702                      }
2703                  };
2704              }
2705  
2706 +            @SuppressWarnings("unchecked")
2707              public Object[] toArray() {
2708                  Object[] source = s.toArray();
2709  
# Line 2698 | Line 2716 | public class Collections {
2716                                   new Object[source.length]);
2717  
2718                  for (int i = 0; i < source.length; i++)
2719 <                    dest[i] = new CheckedEntry<K,V>((Map.Entry<K,V>)source[i],
2720 <                                                    valueType);
2719 >                    dest[i] = checkedEntry((Map.Entry<K,V>)source[i],
2720 >                                           valueType);
2721                  return dest;
2722              }
2723  
2724 +            @SuppressWarnings("unchecked")
2725              public <T> T[] toArray(T[] a) {
2726                  // We don't pass a to s.toArray, to avoid window of
2727                  // vulnerability wherein an unscrupulous multithreaded client
2728                  // could get his hands on raw (unwrapped) Entries from s.
2729 <                Object[] arr = s.toArray(a.length==0 ? a : Arrays.copyOf(a, 0));
2729 >                T[] arr = s.toArray(a.length==0 ? a : Arrays.copyOf(a, 0));
2730  
2731                  for (int i=0; i<arr.length; i++)
2732 <                    arr[i] = new CheckedEntry<K,V>((Map.Entry<K,V>)arr[i],
2733 <                                                   valueType);
2732 >                    arr[i] = (T) checkedEntry((Map.Entry<K,V>)arr[i],
2733 >                                              valueType);
2734                  if (arr.length > a.length)
2735 <                    return (T[])arr;
2735 >                    return arr;
2736  
2737                  System.arraycopy(arr, 0, a, 0, arr.length);
2738                  if (a.length > arr.length)
# Line 2730 | Line 2749 | public class Collections {
2749              public boolean contains(Object o) {
2750                  if (!(o instanceof Map.Entry))
2751                      return false;
2752 <                return s.contains(
2753 <                    new CheckedEntry<K,V>((Map.Entry<K,V>) o, valueType));
2752 >                Map.Entry<?,?> e = (Map.Entry<?,?>) o;
2753 >                return s.contains(
2754 >                    (e instanceof CheckedEntry) ? e : checkedEntry(e, valueType));
2755              }
2756  
2757              /**
2758 <             * The next two methods are overridden to protect against
2759 <             * an unscrupulous collection whose contains(Object o) method
2760 <             * senses when o is a Map.Entry, and calls o.setValue.
2758 >             * The bulk collection methods are overridden to protect
2759 >             * against an unscrupulous collection whose contains(Object o)
2760 >             * method senses when o is a Map.Entry, and calls o.setValue.
2761               */
2762 <            public boolean containsAll(Collection<?> coll) {
2763 <                Iterator<?> e = coll.iterator();
2764 <                while (e.hasNext())
2745 <                    if (!contains(e.next())) // Invokes safe contains() above
2762 >            public boolean containsAll(Collection<?> c) {
2763 >                for (Object o : c)
2764 >                    if (!contains(o)) // Invokes safe contains() above
2765                          return false;
2766                  return true;
2767              }
2768  
2769 +            public boolean remove(Object o) {
2770 +                if (!(o instanceof Map.Entry))
2771 +                    return false;
2772 +                return s.remove(new AbstractMap.SimpleImmutableEntry
2773 +                                <Object, Object>((Map.Entry<?,?>)o));
2774 +            }
2775 +
2776 +            public boolean removeAll(Collection<?> c) {
2777 +                return batchRemove(c, false);
2778 +            }
2779 +            public boolean retainAll(Collection<?> c) {
2780 +                return batchRemove(c, true);
2781 +            }
2782 +            private boolean batchRemove(Collection<?> c, boolean complement) {
2783 +                boolean modified = false;
2784 +                Iterator<Map.Entry<K,V>> it = iterator();
2785 +                while (it.hasNext()) {
2786 +                    if (c.contains(it.next()) != complement) {
2787 +                        it.remove();
2788 +                        modified = true;
2789 +                    }
2790 +                }
2791 +                return modified;
2792 +            }
2793 +
2794              public boolean equals(Object o) {
2795                  if (o == this)
2796                      return true;
2797                  if (!(o instanceof Set))
2798                      return false;
2799                  Set<?> that = (Set<?>) o;
2800 <                if (that.size() != s.size())
2801 <                    return false;
2758 <                return containsAll(that); // Invokes safe containsAll() above
2800 >                return that.size() == s.size()
2801 >                    && containsAll(that); // Invokes safe containsAll() above
2802              }
2803  
2804 +            static <K,V,T> CheckedEntry<K,V,T> checkedEntry(Map.Entry<K,V> e,
2805 +                                                            Class<T> valueType) {
2806 +                return new CheckedEntry<K,V,T>(e, valueType);
2807 +            }
2808 +
2809              /**
2810               * This "wrapper class" serves two purposes: it prevents
2811               * the client from modifying the backing Map, by short-circuiting
2812               * the setValue method, and it protects the backing Map against
2813               * an ill-behaved Map.Entry that attempts to modify another
2814 <             * Map Entry when asked to perform an equality check.
2814 >             * Map.Entry when asked to perform an equality check.
2815               */
2816 <            private static class CheckedEntry<K,V> implements Map.Entry<K,V> {
2817 <                private Map.Entry<K, V> e;
2818 <                private Class<V> valueType;
2816 >            private static class CheckedEntry<K,V,T> implements Map.Entry<K,V> {
2817 >                private final Map.Entry<K, V> e;
2818 >                private final Class<T> valueType;
2819  
2820 <                CheckedEntry(Map.Entry<K, V> e, Class<V> valueType) {
2820 >                CheckedEntry(Map.Entry<K, V> e, Class<T> valueType) {
2821                      this.e = e;
2822                      this.valueType = valueType;
2823                  }
# Line 2779 | Line 2827 | public class Collections {
2827                  public int hashCode()    { return e.hashCode(); }
2828                  public String toString() { return e.toString(); }
2829  
2782
2830                  public V setValue(V value) {
2831 <                    if (!valueType.isInstance(value))
2832 <                        throw new ClassCastException("Attempt to insert " +
2786 <                        value.getClass() +
2787 <                        " value into collection with value type " + valueType);
2831 >                    if (value != null && !valueType.isInstance(value))
2832 >                        throw new ClassCastException(badValueMsg(value));
2833                      return e.setValue(value);
2834                  }
2835  
2836 +                private String badValueMsg(Object value) {
2837 +                    return "Attempt to insert " + value.getClass() +
2838 +                        " value into map with value type " + valueType;
2839 +                }
2840 +
2841                  public boolean equals(Object o) {
2842 +                    if (o == this)
2843 +                        return true;
2844                      if (!(o instanceof Map.Entry))
2845                          return false;
2846 <                    Map.Entry t = (Map.Entry)o;
2847 <                    return eq(e.getKey(),   t.getKey()) &&
2796 <                           eq(e.getValue(), t.getValue());
2846 >                    return e.equals(new AbstractMap.SimpleImmutableEntry
2847 >                                    <Object, Object>((Map.Entry<?,?>)o));
2848                  }
2849              }
2850          }
2851      }
2852  
2853      /**
2854 <     * Returns a dynamically typesafe view of the specified sorted map.  Any
2855 <     * attempt to insert a mapping whose key or value have the wrong type will
2856 <     * result in an immediate <tt>ClassCastException</tt>.  Similarly, any
2857 <     * attempt to modify the value currently associated with a key will result
2858 <     * in an immediate <tt>ClassCastException</tt>, whether the modification
2859 <     * is attempted directly through the map itself, or through a {@link
2860 <     * Map.Entry} instance obtained from the map's {@link Map#entrySet() entry
2861 <     * set} view.
2854 >     * Returns a dynamically typesafe view of the specified sorted map.
2855 >     * Any attempt to insert a mapping whose key or value have the wrong
2856 >     * type will result in an immediate {@link ClassCastException}.
2857 >     * Similarly, any attempt to modify the value currently associated with
2858 >     * a key will result in an immediate {@link ClassCastException},
2859 >     * whether the modification is attempted directly through the map
2860 >     * itself, or through a {@link Map.Entry} instance obtained from the
2861 >     * map's {@link Map#entrySet() entry set} view.
2862       *
2863       * <p>Assuming a map contains no incorrectly typed keys or values
2864       * prior to the time a dynamically typesafe view is generated, and
# Line 2816 | Line 2867 | public class Collections {
2867       * map cannot contain an incorrectly typed key or value.
2868       *
2869       * <p>A discussion of the use of dynamically typesafe views may be
2870 <     * found in the documentation for the {@link #checkedCollection checkedCollection}
2871 <     * method.
2870 >     * found in the documentation for the {@link #checkedCollection
2871 >     * checkedCollection} method.
2872       *
2873       * <p>The returned map will be serializable if the specified map is
2874       * serializable.
2875       *
2876 +     * <p>Since {@code null} is considered to be a value of any reference
2877 +     * type, the returned map permits insertion of null keys or values
2878 +     * whenever the backing map does.
2879 +     *
2880       * @param m the map for which a dynamically typesafe view is to be
2881 <     *             returned
2882 <     * @param keyType the type of key that <tt>m</tt> is permitted to hold
2883 <     * @param valueType the type of value that <tt>m</tt> is permitted to hold
2881 >     *          returned
2882 >     * @param keyType the type of key that {@code m} is permitted to hold
2883 >     * @param valueType the type of value that {@code m} is permitted to hold
2884       * @return a dynamically typesafe view of the specified map
2885       * @since 1.5
2886       */
# Line 2856 | Line 2911 | public class Collections {
2911          public K lastKey()                        { return sm.lastKey(); }
2912  
2913          public SortedMap<K,V> subMap(K fromKey, K toKey) {
2914 <            return new CheckedSortedMap<K,V>(sm.subMap(fromKey, toKey),
2915 <                                             keyType, valueType);
2914 >            return checkedSortedMap(sm.subMap(fromKey, toKey),
2915 >                                    keyType, valueType);
2916          }
2862
2917          public SortedMap<K,V> headMap(K toKey) {
2918 <            return new CheckedSortedMap<K,V>(sm.headMap(toKey),
2865 <                                             keyType, valueType);
2918 >            return checkedSortedMap(sm.headMap(toKey), keyType, valueType);
2919          }
2867
2920          public SortedMap<K,V> tailMap(K fromKey) {
2921 <            return new CheckedSortedMap<K,V>(sm.tailMap(fromKey),
2870 <                                             keyType, valueType);
2921 >            return checkedSortedMap(sm.tailMap(fromKey), keyType, valueType);
2922          }
2923      }
2924  
2925 <    // Miscellaneous
2925 >    // Empty collections
2926 >
2927 >    /**
2928 >     * Returns an iterator that has no elements.  More precisely,
2929 >     *
2930 >     * <ul compact>
2931 >     *
2932 >     * <li>{@link Iterator#hasNext hasNext} always returns {@code
2933 >     * false}.
2934 >     *
2935 >     * <li>{@link Iterator#next next} always throws {@link
2936 >     * NoSuchElementException}.
2937 >     *
2938 >     * <li>{@link Iterator#remove remove} always throws {@link
2939 >     * IllegalStateException}.
2940 >     *
2941 >     * </ul>
2942 >     *
2943 >     * <p>Implementations of this method are permitted, but not
2944 >     * required, to return the same object from multiple invocations.
2945 >     *
2946 >     * @return an empty iterator
2947 >     * @since 1.7
2948 >     */
2949 >    @SuppressWarnings("unchecked")
2950 >    public static <T> Iterator<T> emptyIterator() {
2951 >        return (Iterator<T>) EmptyIterator.EMPTY_ITERATOR;
2952 >    }
2953 >
2954 >    private static class EmptyIterator<E> implements Iterator<E> {
2955 >        static final EmptyIterator<Object> EMPTY_ITERATOR
2956 >            = new EmptyIterator<Object>();
2957 >
2958 >        public boolean hasNext() { return false; }
2959 >        public E next() { throw new NoSuchElementException(); }
2960 >        public void remove() { throw new IllegalStateException(); }
2961 >    }
2962 >
2963 >    /**
2964 >     * Returns a list iterator that has no elements.  More precisely,
2965 >     *
2966 >     * <ul compact>
2967 >     *
2968 >     * <li>{@link Iterator#hasNext hasNext} and {@link
2969 >     * ListIterator#hasPrevious hasPrevious} always return {@code
2970 >     * false}.
2971 >     *
2972 >     * <li>{@link Iterator#next next} and {@link ListIterator#previous
2973 >     * previous} always throw {@link NoSuchElementException}.
2974 >     *
2975 >     * <li>{@link Iterator#remove remove} and {@link ListIterator#set
2976 >     * set} always throw {@link IllegalStateException}.
2977 >     *
2978 >     * <li>{@link ListIterator#add add} always throws {@link
2979 >     * UnsupportedOperationException}.
2980 >     *
2981 >     * <li>{@link ListIterator#nextIndex nextIndex} always returns
2982 >     * {@code 0} .
2983 >     *
2984 >     * <li>{@link ListIterator#previousIndex previousIndex} always
2985 >     * returns {@code -1}.
2986 >     *
2987 >     * </ul>
2988 >     *
2989 >     * <p>Implementations of this method are permitted, but not
2990 >     * required, to return the same object from multiple invocations.
2991 >     *
2992 >     * @return an empty list iterator
2993 >     * @since 1.7
2994 >     */
2995 >    @SuppressWarnings("unchecked")
2996 >    public static <T> ListIterator<T> emptyListIterator() {
2997 >        return (ListIterator<T>) EmptyListIterator.EMPTY_ITERATOR;
2998 >    }
2999 >
3000 >    private static class EmptyListIterator<E>
3001 >        extends EmptyIterator<E>
3002 >        implements ListIterator<E>
3003 >    {
3004 >        static final EmptyListIterator<Object> EMPTY_ITERATOR
3005 >            = new EmptyListIterator<Object>();
3006 >
3007 >        public boolean hasPrevious() { return false; }
3008 >        public E previous() { throw new NoSuchElementException(); }
3009 >        public int nextIndex()     { return 0; }
3010 >        public int previousIndex() { return -1; }
3011 >        public void set(E e) { throw new IllegalStateException(); }
3012 >        public void add(E e) { throw new UnsupportedOperationException(); }
3013 >    }
3014 >
3015 >    /**
3016 >     * Returns an enumeration that has no elements.  More precisely,
3017 >     *
3018 >     * <ul compact>
3019 >     *
3020 >     * <li>{@link Enumeration#hasMoreElements hasMoreElements} always
3021 >     * returns {@code false}.
3022 >     *
3023 >     * <li> {@link Enumeration#nextElement nextElement} always throws
3024 >     * {@link NoSuchElementException}.
3025 >     *
3026 >     * </ul>
3027 >     *
3028 >     * <p>Implementations of this method are permitted, but not
3029 >     * required, to return the same object from multiple invocations.
3030 >     *
3031 >     * @return an empty enumeration
3032 >     * @since 1.7
3033 >     */
3034 >    @SuppressWarnings("unchecked")
3035 >    public static <T> Enumeration<T> emptyEnumeration() {
3036 >        return (Enumeration<T>) EmptyEnumeration.EMPTY_ENUMERATION;
3037 >    }
3038 >
3039 >    private static class EmptyEnumeration<E> implements Enumeration<E> {
3040 >        static final EmptyEnumeration<Object> EMPTY_ENUMERATION
3041 >            = new EmptyEnumeration<Object>();
3042 >
3043 >        public boolean hasMoreElements() { return false; }
3044 >        public E nextElement() { throw new NoSuchElementException(); }
3045 >    }
3046  
3047      /**
3048       * The empty set (immutable).  This set is serializable.
3049       *
3050       * @see #emptySet()
3051       */
3052 <    public static final Set EMPTY_SET = new EmptySet();
3052 >    @SuppressWarnings("unchecked")
3053 >    public static final Set EMPTY_SET = new EmptySet<Object>();
3054  
3055      /**
3056       * Returns the empty set (immutable).  This set is serializable.
# Line 2896 | Line 3068 | public class Collections {
3068       * @see #EMPTY_SET
3069       * @since 1.5
3070       */
3071 +    @SuppressWarnings("unchecked")
3072      public static final <T> Set<T> emptySet() {
3073          return (Set<T>) EMPTY_SET;
3074      }
# Line 2903 | Line 3076 | public class Collections {
3076      /**
3077       * @serial include
3078       */
3079 <    private static class EmptySet extends AbstractSet<Object> implements Serializable {
3080 <        // use serialVersionUID from JDK 1.2.2 for interoperability
3079 >    private static class EmptySet<E>
3080 >        extends AbstractSet<E>
3081 >        implements Serializable
3082 >    {
3083          private static final long serialVersionUID = 1582296315990362920L;
3084  
3085 <        public Iterator<Object> iterator() {
2911 <            return new Iterator<Object>() {
2912 <                public boolean hasNext() {
2913 <                    return false;
2914 <                }
2915 <                public Object next() {
2916 <                    throw new NoSuchElementException();
2917 <                }
2918 <                public void remove() {
2919 <                    throw new UnsupportedOperationException();
2920 <                }
2921 <            };
2922 <        }
3085 >        public Iterator<E> iterator() { return emptyIterator(); }
3086  
3087          public int size() {return 0;}
3088 +        public boolean isEmpty() {return true;}
3089  
3090          public boolean contains(Object obj) {return false;}
3091 +        public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
3092  
3093 <        // Preserves singleton property
3093 >        public Object[] toArray() { return new Object[0]; }
3094 >
3095 >        public <T> T[] toArray(T[] a) {
3096 >            if (a.length > 0)
3097 >                a[0] = null;
3098 >            return a;
3099 >        }
3100 >
3101 >        // Preserves singleton property
3102          private Object readResolve() {
3103              return EMPTY_SET;
3104          }
# Line 2936 | Line 3109 | public class Collections {
3109       *
3110       * @see #emptyList()
3111       */
3112 <    public static final List EMPTY_LIST = new EmptyList();
3112 >    @SuppressWarnings("unchecked")
3113 >    public static final List EMPTY_LIST = new EmptyList<Object>();
3114  
3115      /**
3116       * Returns the empty list (immutable).  This list is serializable.
# Line 2953 | Line 3127 | public class Collections {
3127       * @see #EMPTY_LIST
3128       * @since 1.5
3129       */
3130 +    @SuppressWarnings("unchecked")
3131      public static final <T> List<T> emptyList() {
3132          return (List<T>) EMPTY_LIST;
3133      }
# Line 2960 | Line 3135 | public class Collections {
3135      /**
3136       * @serial include
3137       */
3138 <    private static class EmptyList
3139 <        extends AbstractList<Object>
3138 >    private static class EmptyList<E>
3139 >        extends AbstractList<E>
3140          implements RandomAccess, Serializable {
2966        // use serialVersionUID from JDK 1.2.2 for interoperability
3141          private static final long serialVersionUID = 8842843931221139166L;
3142  
3143 <        public int size() {return 0;}
3143 >        public Iterator<E> iterator() {
3144 >            return emptyIterator();
3145 >        }
3146 >        public ListIterator<E> listIterator() {
3147 >            return emptyListIterator();
3148 >        }
3149 >
3150 >        public int size() {return 0;}
3151 >        public boolean isEmpty() {return true;}
3152  
3153          public boolean contains(Object obj) {return false;}
3154 +        public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
3155 +
3156 +        public Object[] toArray() { return new Object[0]; }
3157 +
3158 +        public <T> T[] toArray(T[] a) {
3159 +            if (a.length > 0)
3160 +                a[0] = null;
3161 +            return a;
3162 +        }
3163  
3164 <        public Object get(int index) {
3164 >        public E get(int index) {
3165              throw new IndexOutOfBoundsException("Index: "+index);
3166          }
3167  
3168 +        public boolean equals(Object o) {
3169 +            return (o instanceof List) && ((List<?>)o).isEmpty();
3170 +        }
3171 +
3172 +        public int hashCode() { return 1; }
3173 +
3174          // Preserves singleton property
3175          private Object readResolve() {
3176              return EMPTY_LIST;
# Line 2986 | Line 3183 | public class Collections {
3183       * @see #emptyMap()
3184       * @since 1.3
3185       */
3186 <    public static final Map EMPTY_MAP = new EmptyMap();
3186 >    @SuppressWarnings("unchecked")
3187 >    public static final Map EMPTY_MAP = new EmptyMap<Object,Object>();
3188  
3189      /**
3190       * Returns the empty map (immutable).  This map is serializable.
# Line 3003 | Line 3201 | public class Collections {
3201       * @see #EMPTY_MAP
3202       * @since 1.5
3203       */
3204 +    @SuppressWarnings("unchecked")
3205      public static final <K,V> Map<K,V> emptyMap() {
3206          return (Map<K,V>) EMPTY_MAP;
3207      }
3208  
3209 <    private static class EmptyMap
3210 <        extends AbstractMap<Object,Object>
3211 <        implements Serializable {
3212 <
3209 >    /**
3210 >     * @serial include
3211 >     */
3212 >    private static class EmptyMap<K,V>
3213 >        extends AbstractMap<K,V>
3214 >        implements Serializable
3215 >    {
3216          private static final long serialVersionUID = 6428348081105594320L;
3217  
3218          public int size()                          {return 0;}
3017
3219          public boolean isEmpty()                   {return true;}
3019
3220          public boolean containsKey(Object key)     {return false;}
3021
3221          public boolean containsValue(Object value) {return false;}
3222 <
3223 <        public Object get(Object key)              {return null;}
3224 <
3225 <        public Set<Object> keySet()                {return Collections.<Object>emptySet();}
3027 <
3028 <        public Collection<Object> values()         {return Collections.<Object>emptySet();}
3029 <
3030 <        public Set<Map.Entry<Object,Object>> entrySet() {
3031 <            return Collections.emptySet();
3032 <        }
3222 >        public V get(Object key)                   {return null;}
3223 >        public Set<K> keySet()                     {return emptySet();}
3224 >        public Collection<V> values()              {return emptySet();}
3225 >        public Set<Map.Entry<K,V>> entrySet()      {return emptySet();}
3226  
3227          public boolean equals(Object o) {
3228 <            return (o instanceof Map) && ((Map)o).size()==0;
3228 >            return (o instanceof Map) && ((Map<?,?>)o).isEmpty();
3229          }
3230  
3231          public int hashCode()                      {return 0;}
# Line 3043 | Line 3236 | public class Collections {
3236          }
3237      }
3238  
3239 +    // Singleton collections
3240 +
3241      /**
3242       * Returns an immutable set containing only the specified object.
3243       * The returned set is serializable.
# Line 3054 | Line 3249 | public class Collections {
3249          return new SingletonSet<T>(o);
3250      }
3251  
3252 +    static <E> Iterator<E> singletonIterator(final E e) {
3253 +        return new Iterator<E>() {
3254 +            private boolean hasNext = true;
3255 +            public boolean hasNext() {
3256 +                return hasNext;
3257 +            }
3258 +            public E next() {
3259 +                if (hasNext) {
3260 +                    hasNext = false;
3261 +                    return e;
3262 +                }
3263 +                throw new NoSuchElementException();
3264 +            }
3265 +            public void remove() {
3266 +                throw new UnsupportedOperationException();
3267 +            }
3268 +        };
3269 +    }
3270 +
3271      /**
3272       * @serial include
3273       */
# Line 3061 | Line 3275 | public class Collections {
3275          extends AbstractSet<E>
3276          implements Serializable
3277      {
3064        // use serialVersionUID from JDK 1.2.2 for interoperability
3278          private static final long serialVersionUID = 3193687207550431679L;
3279  
3280          final private E element;
# Line 3069 | Line 3282 | public class Collections {
3282          SingletonSet(E e) {element = e;}
3283  
3284          public Iterator<E> iterator() {
3285 <            return new Iterator<E>() {
3073 <                private boolean hasNext = true;
3074 <                public boolean hasNext() {
3075 <                    return hasNext;
3076 <                }
3077 <                public E next() {
3078 <                    if (hasNext) {
3079 <                        hasNext = false;
3080 <                        return element;
3081 <                    }
3082 <                    throw new NoSuchElementException();
3083 <                }
3084 <                public void remove() {
3085 <                    throw new UnsupportedOperationException();
3086 <                }
3087 <            };
3285 >            return singletonIterator(element);
3286          }
3287  
3288          public int size() {return 1;}
# Line 3104 | Line 3302 | public class Collections {
3302          return new SingletonList<T>(o);
3303      }
3304  
3305 +    /**
3306 +     * @serial include
3307 +     */
3308      private static class SingletonList<E>
3309          extends AbstractList<E>
3310          implements RandomAccess, Serializable {
3311  
3312 <        static final long serialVersionUID = 3093736618740652951L;
3312 >        private static final long serialVersionUID = 3093736618740652951L;
3313  
3314          private final E element;
3315  
3316          SingletonList(E obj)                {element = obj;}
3317  
3318 +        public Iterator<E> iterator() {
3319 +            return singletonIterator(element);
3320 +        }
3321 +
3322          public int size()                   {return 1;}
3323  
3324          public boolean contains(Object obj) {return eq(obj, element);}
# Line 3139 | Line 3344 | public class Collections {
3344          return new SingletonMap<K,V>(key, value);
3345      }
3346  
3347 +    /**
3348 +     * @serial include
3349 +     */
3350      private static class SingletonMap<K,V>
3351            extends AbstractMap<K,V>
3352            implements Serializable {
# Line 3187 | Line 3395 | public class Collections {
3395  
3396      }
3397  
3398 +    // Miscellaneous
3399 +
3400      /**
3401       * Returns an immutable list consisting of <tt>n</tt> copies of the
3402       * specified object.  The newly allocated data object is tiny (it contains
# Line 3215 | Line 3425 | public class Collections {
3425          extends AbstractList<E>
3426          implements RandomAccess, Serializable
3427      {
3428 <        static final long serialVersionUID = 2739099268398711800L;
3428 >        private static final long serialVersionUID = 2739099268398711800L;
3429  
3430          final int n;
3431          final E element;
# Line 3279 | Line 3489 | public class Collections {
3489              if (fromIndex > toIndex)
3490                  throw new IllegalArgumentException("fromIndex(" + fromIndex +
3491                                                     ") > toIndex(" + toIndex + ")");
3492 <            return new CopiesList(toIndex - fromIndex, element);
3492 >            return new CopiesList<E>(toIndex - fromIndex, element);
3493          }
3494      }
3495  
# Line 3303 | Line 3513 | public class Collections {
3513       * @see Comparable
3514       */
3515      public static <T> Comparator<T> reverseOrder() {
3516 <        return (Comparator<T>) REVERSE_ORDER;
3516 >        return (Comparator<T>) ReverseComparator.REVERSE_ORDER;
3517      }
3518  
3309    private static final Comparator REVERSE_ORDER = new ReverseComparator();
3310
3519      /**
3520       * @serial include
3521       */
3522 <    private static class ReverseComparator<T>
3522 >    private static class ReverseComparator
3523          implements Comparator<Comparable<Object>>, Serializable {
3524  
3317        // use serialVersionUID from JDK 1.2.2 for interoperability
3525          private static final long serialVersionUID = 7207038068494060240L;
3526  
3527 +        static final ReverseComparator REVERSE_ORDER
3528 +            = new ReverseComparator();
3529 +
3530          public int compare(Comparable<Object> c1, Comparable<Object> c2) {
3531              return c2.compareTo(c1);
3532          }
3533 +
3534 +        private Object readResolve() { return reverseOrder(); }
3535      }
3536  
3537      /**
# Line 3333 | Line 3545 | public class Collections {
3545       * comparator is also serializable or null).
3546       *
3547       * @return a comparator that imposes the reverse ordering of the
3548 <     *     specified comparator.
3548 >     *         specified comparator
3549       * @since 1.5
3550       */
3551      public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) {
3552          if (cmp == null)
3553 <            return new ReverseComparator();  // Unchecked warning!!
3553 >            return reverseOrder();
3554 >
3555 >        if (cmp instanceof ReverseComparator2)
3556 >            return ((ReverseComparator2<T>)cmp).cmp;
3557  
3558          return new ReverseComparator2<T>(cmp);
3559      }
# Line 3358 | Line 3573 | public class Collections {
3573           *
3574           * @serial
3575           */
3576 <        private Comparator<T> cmp;
3576 >        final Comparator<T> cmp;
3577  
3578          ReverseComparator2(Comparator<T> cmp) {
3579              assert cmp != null;
# Line 3368 | Line 3583 | public class Collections {
3583          public int compare(T t1, T t2) {
3584              return cmp.compare(t2, t1);
3585          }
3586 +
3587 +        public boolean equals(Object o) {
3588 +            return (o == this) ||
3589 +                (o instanceof ReverseComparator2 &&
3590 +                 cmp.equals(((ReverseComparator2)o).cmp));
3591 +        }
3592 +
3593 +        public int hashCode() {
3594 +            return cmp.hashCode() ^ Integer.MIN_VALUE;
3595 +        }
3596      }
3597  
3598      /**
# Line 3381 | Line 3606 | public class Collections {
3606       */
3607      public static <T> Enumeration<T> enumeration(final Collection<T> c) {
3608          return new Enumeration<T>() {
3609 <            Iterator<T> i = c.iterator();
3609 >            private final Iterator<T> i = c.iterator();
3610  
3611              public boolean hasMoreElements() {
3612                  return i.hasNext();
# Line 3418 | Line 3643 | public class Collections {
3643      /**
3644       * Returns true if the specified arguments are equal, or both null.
3645       */
3646 <    private static boolean eq(Object o1, Object o2) {
3647 <        return (o1==null ? o2==null : o1.equals(o2));
3646 >    static boolean eq(Object o1, Object o2) {
3647 >        return o1==null ? o2==null : o1.equals(o2);
3648      }
3649  
3650      /**
# Line 3557 | Line 3782 | public class Collections {
3782          return new SetFromMap<E>(map);
3783      }
3784  
3785 +    /**
3786 +     * @serial include
3787 +     */
3788      private static class SetFromMap<E> extends AbstractSet<E>
3789          implements Set<E>, Serializable
3790      {
3791          private final Map<E, Boolean> m;  // The backing map
3792 <        private transient Set<E> keySet;  // Its keySet
3792 >        private transient Set<E> s;       // Its keySet
3793  
3794          SetFromMap(Map<E, Boolean> map) {
3795              if (!map.isEmpty())
3796                  throw new IllegalArgumentException("Map is non-empty");
3797              m = map;
3798 <            keySet = map.keySet();
3798 >            s = map.keySet();
3799          }
3800  
3801 +        public void clear()               {        m.clear(); }
3802          public int size()                 { return m.size(); }
3803          public boolean isEmpty()          { return m.isEmpty(); }
3804          public boolean contains(Object o) { return m.containsKey(o); }
3576        public Iterator<E> iterator()     { return keySet.iterator(); }
3577        public Object[] toArray()         { return keySet.toArray(); }
3578        public <T> T[] toArray(T[] a)     { return keySet.toArray(a); }
3579        public boolean add(E e) {
3580            return m.put(e, Boolean.TRUE) == null;
3581        }
3805          public boolean remove(Object o)   { return m.remove(o) != null; }
3806 <
3807 <        public boolean removeAll(Collection<?> c) {
3808 <            return keySet.removeAll(c);
3809 <        }
3810 <        public boolean retainAll(Collection<?> c) {
3811 <            return keySet.retainAll(c);
3812 <        }
3813 <        public void clear()               { m.clear(); }
3814 <        public boolean equals(Object o)   { return keySet.equals(o); }
3815 <        public int hashCode()             { return keySet.hashCode(); }
3806 >        public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
3807 >        public Iterator<E> iterator()     { return s.iterator(); }
3808 >        public Object[] toArray()         { return s.toArray(); }
3809 >        public <T> T[] toArray(T[] a)     { return s.toArray(a); }
3810 >        public String toString()          { return s.toString(); }
3811 >        public int hashCode()             { return s.hashCode(); }
3812 >        public boolean equals(Object o)   { return o == this || s.equals(o); }
3813 >        public boolean containsAll(Collection<?> c) {return s.containsAll(c);}
3814 >        public boolean removeAll(Collection<?> c)   {return s.removeAll(c);}
3815 >        public boolean retainAll(Collection<?> c)   {return s.retainAll(c);}
3816 >        // addAll is the only inherited implementation
3817  
3818          private static final long serialVersionUID = 2454657854757543876L;
3819  
3820 <        private void readObject(java.io.ObjectInputStream s)
3820 >        private void readObject(java.io.ObjectInputStream stream)
3821              throws IOException, ClassNotFoundException
3822          {
3823 <            s.defaultReadObject();
3824 <            keySet = m.keySet();
3823 >            stream.defaultReadObject();
3824 >            s = m.keySet();
3825          }
3826      }
3827  
# Line 3608 | Line 3832 | public class Collections {
3832       * view can be useful when you would like to use a method
3833       * requiring a <tt>Queue</tt> but you need Lifo ordering.
3834       *
3835 +     * <p>Each method invocation on the queue returned by this method
3836 +     * results in exactly one method invocation on the backing deque, with
3837 +     * one exception.  The {@link Queue#addAll addAll} method is
3838 +     * implemented as a sequence of {@link Deque#addFirst addFirst}
3839 +     * invocations on the backing deque.
3840 +     *
3841       * @param deque the deque
3842       * @return the queue
3843       * @since  1.6
# Line 3616 | Line 3846 | public class Collections {
3846          return new AsLIFOQueue<T>(deque);
3847      }
3848  
3849 +    /**
3850 +     * @serial include
3851 +     */
3852      static class AsLIFOQueue<E> extends AbstractQueue<E>
3853          implements Queue<E>, Serializable {
3854          private static final long serialVersionUID = 1802017725587941708L;
3855          private final Deque<E> q;
3856 <        AsLIFOQueue(Deque<E> q)            { this.q = q; }
3857 <        public boolean add(E e)            { q.addFirst(e); return true; }
3858 <        public boolean offer(E e)          { return q.offerFirst(e); }
3859 <        public E poll()                    { return q.pollFirst(); }
3860 <        public E remove()                  { return q.removeFirst(); }
3861 <        public E peek()                    { return q.peekFirst(); }
3862 <        public E element()                 { return q.getFirst(); }
3863 <        public int size()                  { return q.size(); }
3864 <        public boolean isEmpty()           { return q.isEmpty(); }
3865 <        public boolean contains(Object o)  { return q.contains(o); }
3866 <        public Iterator<E> iterator()      { return q.iterator(); }
3867 <        public Object[] toArray()          { return q.toArray(); }
3868 <        public <T> T[] toArray(T[] a)      { return q.toArray(a); }
3869 <        public boolean remove(Object o)    { return q.remove(o); }
3870 <        public void clear()                { q.clear(); }
3856 >        AsLIFOQueue(Deque<E> q)           { this.q = q; }
3857 >        public boolean add(E e)           { q.addFirst(e); return true; }
3858 >        public boolean offer(E e)         { return q.offerFirst(e); }
3859 >        public E poll()                   { return q.pollFirst(); }
3860 >        public E remove()                 { return q.removeFirst(); }
3861 >        public E peek()                   { return q.peekFirst(); }
3862 >        public E element()                { return q.getFirst(); }
3863 >        public void clear()               {        q.clear(); }
3864 >        public int size()                 { return q.size(); }
3865 >        public boolean isEmpty()          { return q.isEmpty(); }
3866 >        public boolean contains(Object o) { return q.contains(o); }
3867 >        public boolean remove(Object o)   { return q.remove(o); }
3868 >        public Iterator<E> iterator()     { return q.iterator(); }
3869 >        public Object[] toArray()         { return q.toArray(); }
3870 >        public <T> T[] toArray(T[] a)     { return q.toArray(a); }
3871 >        public String toString()          { return q.toString(); }
3872 >        public boolean containsAll(Collection<?> c) {return q.containsAll(c);}
3873 >        public boolean removeAll(Collection<?> c)   {return q.removeAll(c);}
3874 >        public boolean retainAll(Collection<?> c)   {return q.retainAll(c);}
3875 >        // We use inherited addAll; forwarding addAll would be wrong
3876      }
3877   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines