• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 package java.util;
19 
20 import java.io.IOException;
21 import java.io.ObjectInputStream;
22 import java.io.ObjectOutputStream;
23 import java.io.ObjectStreamException;
24 import java.io.Serializable;
25 import java.lang.reflect.Array;
26 
27 /**
28  * {@code Collections} contains static methods which operate on
29  * {@code Collection} classes.
30  *
31  * @since 1.2
32  */
33 public class Collections {
34 
35     private static final class CopiesList<E> extends AbstractList<E> implements
36             Serializable {
37         private static final long serialVersionUID = 2739099268398711800L;
38 
39         private final int n;
40 
41         private final E element;
42 
CopiesList(int length, E object)43         CopiesList(int length, E object) {
44             if (length < 0) {
45                 throw new IllegalArgumentException();
46             }
47             n = length;
48             element = object;
49         }
50 
51         @Override
contains(Object object)52         public boolean contains(Object object) {
53             return element == null ? object == null : element.equals(object);
54         }
55 
56         @Override
size()57         public int size() {
58             return n;
59         }
60 
61         @Override
get(int location)62         public E get(int location) {
63             if (0 <= location && location < n) {
64                 return element;
65             }
66             throw new IndexOutOfBoundsException();
67         }
68     }
69 
70     @SuppressWarnings("unchecked")
71     private static final class EmptyList extends AbstractList implements
72             RandomAccess, Serializable {
73         private static final long serialVersionUID = 8842843931221139166L;
74 
75         @Override
contains(Object object)76         public boolean contains(Object object) {
77             return false;
78         }
79 
80         @Override
size()81         public int size() {
82             return 0;
83         }
84 
85         @Override
get(int location)86         public Object get(int location) {
87             throw new IndexOutOfBoundsException();
88         }
89 
readResolve()90         private Object readResolve() {
91             return Collections.EMPTY_LIST;
92         }
93     }
94 
95     @SuppressWarnings("unchecked")
96     private static final class EmptySet extends AbstractSet implements
97             Serializable {
98         private static final long serialVersionUID = 1582296315990362920L;
99 
100         @Override
contains(Object object)101         public boolean contains(Object object) {
102             return false;
103         }
104 
105         @Override
size()106         public int size() {
107             return 0;
108         }
109 
110         @Override
iterator()111         public Iterator iterator() {
112             return new Iterator() {
113                 public boolean hasNext() {
114                     return false;
115                 }
116 
117                 public Object next() {
118                     throw new NoSuchElementException();
119                 }
120 
121                 public void remove() {
122                     throw new UnsupportedOperationException();
123                 }
124             };
125         }
126 
readResolve()127         private Object readResolve() {
128             return Collections.EMPTY_SET;
129         }
130     }
131 
132     @SuppressWarnings("unchecked")
133     private static final class EmptyMap extends AbstractMap implements
134             Serializable {
135         private static final long serialVersionUID = 6428348081105594320L;
136 
137         @Override
138         public boolean containsKey(Object key) {
139             return false;
140         }
141 
142         @Override
143         public boolean containsValue(Object value) {
144             return false;
145         }
146 
147         @Override
148         public Set entrySet() {
149             return EMPTY_SET;
150         }
151 
152         @Override
153         public Object get(Object key) {
154             return null;
155         }
156 
157         @Override
158         public Set keySet() {
159             return EMPTY_SET;
160         }
161 
162         @Override
163         public Collection values() {
164             return EMPTY_LIST;
165         }
166 
167         private Object readResolve() {
168             return Collections.EMPTY_MAP;
169         }
170     }
171 
172     /**
173      * An empty immutable instance of {@link List}.
174      */
175     @SuppressWarnings("unchecked")
176     public static final List EMPTY_LIST = new EmptyList();
177 
178     /**
179      * An empty immutable instance of {@link Set}.
180      */
181     @SuppressWarnings("unchecked")
182     public static final Set EMPTY_SET = new EmptySet();
183 
184     /**
185      * An empty immutable instance of {@link Map}.
186      */
187     @SuppressWarnings("unchecked")
188     public static final Map EMPTY_MAP = new EmptyMap();
189 
190     /**
191      * This class is a singleton so that equals() and hashCode() work properly.
192      */
193     private static final class ReverseComparator<T> implements Comparator<T>,
194             Serializable {
195 
196         private static final ReverseComparator<Object> INSTANCE
197                 = new ReverseComparator<Object>();
198 
199         private static final long serialVersionUID = 7207038068494060240L;
200 
201         @SuppressWarnings("unchecked")
202         public int compare(T o1, T o2) {
203             Comparable<T> c2 = (Comparable<T>) o2;
204             return c2.compareTo(o1);
205         }
206 
207         private Object readResolve() throws ObjectStreamException {
208             return INSTANCE;
209         }
210     }
211 
212     private static final class ReverseComparator2<T>
213             implements Comparator<T>, Serializable {
214         private static final long serialVersionUID = 4374092139857L;
215         private final Comparator<T> cmp;
216 
217         ReverseComparator2(Comparator<T> comparator) {
218             this.cmp = comparator;
219         }
220 
221         public int compare(T o1, T o2) {
222             return cmp.compare(o2, o1);
223         }
224 
225         @Override public boolean equals(Object o) {
226             return o instanceof ReverseComparator2
227                     && ((ReverseComparator2) o).cmp.equals(cmp);
228         }
229 
230         @Override public int hashCode() {
231             return ~cmp.hashCode();
232         }
233     }
234 
235     private static final class SingletonSet<E> extends AbstractSet<E> implements
236             Serializable {
237         private static final long serialVersionUID = 3193687207550431679L;
238 
239         final E element;
240 
241         SingletonSet(E object) {
242             element = object;
243         }
244 
245         @Override
246         public boolean contains(Object object) {
247             return element == null ? object == null : element.equals(object);
248         }
249 
250         @Override
251         public int size() {
252             return 1;
253         }
254 
255         @Override
256         public Iterator<E> iterator() {
257             return new Iterator<E>() {
258                 boolean hasNext = true;
259 
260                 public boolean hasNext() {
261                     return hasNext;
262                 }
263 
264                 public E next() {
265                     if (hasNext) {
266                         hasNext = false;
267                         return element;
268                     }
269                     throw new NoSuchElementException();
270                 }
271 
272                 public void remove() {
273                     throw new UnsupportedOperationException();
274                 }
275             };
276         }
277     }
278 
279     private static final class SingletonList<E> extends AbstractList<E>
280             implements Serializable {
281         private static final long serialVersionUID = 3093736618740652951L;
282 
283         final E element;
284 
285         SingletonList(E object) {
286             element = object;
287         }
288 
289         @Override
290         public boolean contains(Object object) {
291             return element == null ? object == null : element.equals(object);
292         }
293 
294         @Override
295         public E get(int location) {
296             if (location == 0) {
297                 return element;
298             }
299             throw new IndexOutOfBoundsException();
300         }
301 
302         @Override
303         public int size() {
304             return 1;
305         }
306     }
307 
308     private static final class SingletonMap<K, V> extends AbstractMap<K, V>
309             implements Serializable {
310         private static final long serialVersionUID = -6979724477215052911L;
311 
312         final K k;
313 
314         final V v;
315 
316         SingletonMap(K key, V value) {
317             k = key;
318             v = value;
319         }
320 
321         @Override
322         public boolean containsKey(Object key) {
323             return k == null ? key == null : k.equals(key);
324         }
325 
326         @Override
327         public boolean containsValue(Object value) {
328             return v == null ? value == null : v.equals(value);
329         }
330 
331         @Override
332         public V get(Object key) {
333             if (containsKey(key)) {
334                 return v;
335             }
336             return null;
337         }
338 
339         @Override
340         public int size() {
341             return 1;
342         }
343 
344         @Override
345         public Set<Map.Entry<K, V>> entrySet() {
346             return new AbstractSet<Map.Entry<K, V>>() {
347                 @Override
348                 public boolean contains(Object object) {
349                     if (object instanceof Map.Entry) {
350                         Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
351                         return containsKey(entry.getKey())
352                                 && containsValue(entry.getValue());
353                     }
354                     return false;
355                 }
356 
357                 @Override
358                 public int size() {
359                     return 1;
360                 }
361 
362                 @Override
363                 public Iterator<Map.Entry<K, V>> iterator() {
364                     return new Iterator<Map.Entry<K, V>>() {
365                         boolean hasNext = true;
366 
367                         public boolean hasNext() {
368                             return hasNext;
369                         }
370 
371                         public Map.Entry<K, V> next() {
372                             if (!hasNext) {
373                                 throw new NoSuchElementException();
374                             }
375 
376                             hasNext = false;
377                             return new MapEntry<K, V>(k, v) {
378                                 @Override
379                                 public V setValue(V value) {
380                                     throw new UnsupportedOperationException();
381                                 }
382                             };
383                         }
384 
385                         public void remove() {
386                             throw new UnsupportedOperationException();
387                         }
388                     };
389                 }
390             };
391         }
392     }
393 
394     static class SynchronizedCollection<E> implements Collection<E>,
395             Serializable {
396         private static final long serialVersionUID = 3053995032091335093L;
397 
398         final Collection<E> c;
399 
400         final Object mutex;
401 
402         SynchronizedCollection(Collection<E> collection) {
403             c = collection;
404             mutex = this;
405         }
406 
407         SynchronizedCollection(Collection<E> collection, Object mutex) {
408             c = collection;
409             this.mutex = mutex;
410         }
411 
412         public boolean add(E object) {
413             synchronized (mutex) {
414                 return c.add(object);
415             }
416         }
417 
418         public boolean addAll(Collection<? extends E> collection) {
419             synchronized (mutex) {
420                 return c.addAll(collection);
421             }
422         }
423 
424         public void clear() {
425             synchronized (mutex) {
426                 c.clear();
427             }
428         }
429 
430         public boolean contains(Object object) {
431             synchronized (mutex) {
432                 return c.contains(object);
433             }
434         }
435 
436         public boolean containsAll(Collection<?> collection) {
437             synchronized (mutex) {
438                 return c.containsAll(collection);
439             }
440         }
441 
442         public boolean isEmpty() {
443             synchronized (mutex) {
444                 return c.isEmpty();
445             }
446         }
447 
448         public Iterator<E> iterator() {
449             synchronized (mutex) {
450                 return c.iterator();
451             }
452         }
453 
454         public boolean remove(Object object) {
455             synchronized (mutex) {
456                 return c.remove(object);
457             }
458         }
459 
460         public boolean removeAll(Collection<?> collection) {
461             synchronized (mutex) {
462                 return c.removeAll(collection);
463             }
464         }
465 
466         public boolean retainAll(Collection<?> collection) {
467             synchronized (mutex) {
468                 return c.retainAll(collection);
469             }
470         }
471 
472         public int size() {
473             synchronized (mutex) {
474                 return c.size();
475             }
476         }
477 
478         public java.lang.Object[] toArray() {
479             synchronized (mutex) {
480                 return c.toArray();
481             }
482         }
483 
484         @Override
485         public String toString() {
486             synchronized (mutex) {
487                 return c.toString();
488             }
489         }
490 
491         public <T> T[] toArray(T[] array) {
492             synchronized (mutex) {
493                 return c.toArray(array);
494             }
495         }
496 
497         private void writeObject(ObjectOutputStream stream) throws IOException {
498             synchronized (mutex) {
499                 stream.defaultWriteObject();
500             }
501         }
502     }
503 
504     static class SynchronizedRandomAccessList<E> extends SynchronizedList<E>
505             implements RandomAccess {
506         private static final long serialVersionUID = 1530674583602358482L;
507 
508         SynchronizedRandomAccessList(List<E> l) {
509             super(l);
510         }
511 
512         SynchronizedRandomAccessList(List<E> l, Object mutex) {
513             super(l, mutex);
514         }
515 
516         @Override
517         public List<E> subList(int start, int end) {
518             synchronized (mutex) {
519                 return new SynchronizedRandomAccessList<E>(list.subList(start,
520                         end), mutex);
521             }
522         }
523 
524         /**
525          * Replaces this SynchronizedRandomAccessList with a SynchronizedList so
526          * that JREs before 1.4 can deserialize this object without any
527          * problems. This is necessary since RandomAccess API was introduced
528          * only in 1.4.
529          * <p>
530          *
531          * @return SynchronizedList
532          *
533          * @see SynchronizedList#readResolve()
534          */
535         private Object writeReplace() {
536             return new SynchronizedList<E>(list);
537         }
538     }
539 
540     static class SynchronizedList<E> extends SynchronizedCollection<E>
541             implements List<E> {
542         private static final long serialVersionUID = -7754090372962971524L;
543 
544         final List<E> list;
545 
546         SynchronizedList(List<E> l) {
547             super(l);
548             list = l;
549         }
550 
551         SynchronizedList(List<E> l, Object mutex) {
552             super(l, mutex);
553             list = l;
554         }
555 
556         public void add(int location, E object) {
557             synchronized (mutex) {
558                 list.add(location, object);
559             }
560         }
561 
562         public boolean addAll(int location, Collection<? extends E> collection) {
563             synchronized (mutex) {
564                 return list.addAll(location, collection);
565             }
566         }
567 
568         @Override
569         public boolean equals(Object object) {
570             synchronized (mutex) {
571                 return list.equals(object);
572             }
573         }
574 
575         public E get(int location) {
576             synchronized (mutex) {
577                 return list.get(location);
578             }
579         }
580 
581         @Override
582         public int hashCode() {
583             synchronized (mutex) {
584                 return list.hashCode();
585             }
586         }
587 
588         public int indexOf(Object object) {
589             final int size;
590             final Object[] array;
591             synchronized (mutex) {
592                 size = list.size();
593                 array = new Object[size];
594                 list.toArray(array);
595             }
596             if (null != object)
597                 for (int i = 0; i < size; i++) {
598                     if (object.equals(array[i])) {
599                         return i;
600                     }
601                 }
602             else {
603                 for (int i = 0; i < size; i++) {
604                     if (null == array[i]) {
605                         return i;
606                     }
607                 }
608             }
609             return -1;
610         }
611 
612         public int lastIndexOf(Object object) {
613             final int size;
614             final Object[] array;
615             synchronized (mutex) {
616                 size = list.size();
617                 array = new Object[size];
618                 list.toArray(array);
619             }
620             if (null != object)
621                 for (int i = size - 1; i >= 0; i--) {
622                     if (object.equals(array[i])) {
623                         return i;
624                     }
625                 }
626             else {
627                 for (int i = size - 1; i >= 0; i--) {
628                     if (null == array[i]) {
629                         return i;
630                     }
631                 }
632             }
633             return -1;
634         }
635 
636         public ListIterator<E> listIterator() {
637             synchronized (mutex) {
638                 return list.listIterator();
639             }
640         }
641 
642         public ListIterator<E> listIterator(int location) {
643             synchronized (mutex) {
644                 return list.listIterator(location);
645             }
646         }
647 
648         public E remove(int location) {
649             synchronized (mutex) {
650                 return list.remove(location);
651             }
652         }
653 
654         public E set(int location, E object) {
655             synchronized (mutex) {
656                 return list.set(location, object);
657             }
658         }
659 
660         public List<E> subList(int start, int end) {
661             synchronized (mutex) {
662                 return new SynchronizedList<E>(list.subList(start, end), mutex);
663             }
664         }
665 
666         private void writeObject(ObjectOutputStream stream) throws IOException {
667             synchronized (mutex) {
668                 stream.defaultWriteObject();
669             }
670         }
671 
672         /**
673          * Resolves SynchronizedList instances to SynchronizedRandomAccessList
674          * instances if the underlying list is a Random Access list.
675          * <p>
676          * This is necessary since SynchronizedRandomAccessList instances are
677          * replaced with SynchronizedList instances during serialization for
678          * compliance with JREs before 1.4.
679          * <p>
680          *
681          * @return a SynchronizedList instance if the underlying list implements
682          *         RandomAccess interface, or this same object if not.
683          *
684          * @see SynchronizedRandomAccessList#writeReplace()
685          */
686         private Object readResolve() {
687             if (list instanceof RandomAccess) {
688                 return new SynchronizedRandomAccessList<E>(list, mutex);
689             }
690             return this;
691         }
692     }
693 
694     static class SynchronizedMap<K, V> implements Map<K, V>, Serializable {
695         private static final long serialVersionUID = 1978198479659022715L;
696 
697         private final Map<K, V> m;
698 
699         final Object mutex;
700 
701         SynchronizedMap(Map<K, V> map) {
702             m = map;
703             mutex = this;
704         }
705 
706         SynchronizedMap(Map<K, V> map, Object mutex) {
707             m = map;
708             this.mutex = mutex;
709         }
710 
711         public void clear() {
712             synchronized (mutex) {
713                 m.clear();
714             }
715         }
716 
717         public boolean containsKey(Object key) {
718             synchronized (mutex) {
719                 return m.containsKey(key);
720             }
721         }
722 
723         public boolean containsValue(Object value) {
724             synchronized (mutex) {
725                 return m.containsValue(value);
726             }
727         }
728 
729         public Set<Map.Entry<K, V>> entrySet() {
730             synchronized (mutex) {
731                 return new SynchronizedSet<Map.Entry<K, V>>(m.entrySet(), mutex);
732             }
733         }
734 
735         @Override
736         public boolean equals(Object object) {
737             synchronized (mutex) {
738                 return m.equals(object);
739             }
740         }
741 
742         public V get(Object key) {
743             synchronized (mutex) {
744                 return m.get(key);
745             }
746         }
747 
748         @Override
749         public int hashCode() {
750             synchronized (mutex) {
751                 return m.hashCode();
752             }
753         }
754 
755         public boolean isEmpty() {
756             synchronized (mutex) {
757                 return m.isEmpty();
758             }
759         }
760 
761         public Set<K> keySet() {
762             synchronized (mutex) {
763                 return new SynchronizedSet<K>(m.keySet(), mutex);
764             }
765         }
766 
767         public V put(K key, V value) {
768             synchronized (mutex) {
769                 return m.put(key, value);
770             }
771         }
772 
773         public void putAll(Map<? extends K, ? extends V> map) {
774             synchronized (mutex) {
775                 m.putAll(map);
776             }
777         }
778 
779         public V remove(Object key) {
780             synchronized (mutex) {
781                 return m.remove(key);
782             }
783         }
784 
785         public int size() {
786             synchronized (mutex) {
787                 return m.size();
788             }
789         }
790 
791         public Collection<V> values() {
792             synchronized (mutex) {
793                 return new SynchronizedCollection<V>(m.values(), mutex);
794             }
795         }
796 
797         @Override
798         public String toString() {
799             synchronized (mutex) {
800                 return m.toString();
801             }
802         }
803 
804         private void writeObject(ObjectOutputStream stream) throws IOException {
805             synchronized (mutex) {
806                 stream.defaultWriteObject();
807             }
808         }
809     }
810 
811     static class SynchronizedSet<E> extends SynchronizedCollection<E> implements
812             Set<E> {
813         private static final long serialVersionUID = 487447009682186044L;
814 
815         SynchronizedSet(Set<E> set) {
816             super(set);
817         }
818 
819         SynchronizedSet(Set<E> set, Object mutex) {
820             super(set, mutex);
821         }
822 
823         @Override
824         public boolean equals(Object object) {
825             synchronized (mutex) {
826                 return c.equals(object);
827             }
828         }
829 
830         @Override
831         public int hashCode() {
832             synchronized (mutex) {
833                 return c.hashCode();
834             }
835         }
836 
837         private void writeObject(ObjectOutputStream stream) throws IOException {
838             synchronized (mutex) {
839                 stream.defaultWriteObject();
840             }
841         }
842     }
843 
844     static class SynchronizedSortedMap<K, V> extends SynchronizedMap<K, V>
845             implements SortedMap<K, V> {
846         private static final long serialVersionUID = -8798146769416483793L;
847 
848         private final SortedMap<K, V> sm;
849 
850         SynchronizedSortedMap(SortedMap<K, V> map) {
851             super(map);
852             sm = map;
853         }
854 
855         SynchronizedSortedMap(SortedMap<K, V> map, Object mutex) {
856             super(map, mutex);
857             sm = map;
858         }
859 
860         public Comparator<? super K> comparator() {
861             synchronized (mutex) {
862                 return sm.comparator();
863             }
864         }
865 
866         public K firstKey() {
867             synchronized (mutex) {
868                 return sm.firstKey();
869             }
870         }
871 
872         public SortedMap<K, V> headMap(K endKey) {
873             synchronized (mutex) {
874                 return new SynchronizedSortedMap<K, V>(sm.headMap(endKey),
875                         mutex);
876             }
877         }
878 
879         public K lastKey() {
880             synchronized (mutex) {
881                 return sm.lastKey();
882             }
883         }
884 
885         public SortedMap<K, V> subMap(K startKey, K endKey) {
886             synchronized (mutex) {
887                 return new SynchronizedSortedMap<K, V>(sm.subMap(startKey,
888                         endKey), mutex);
889             }
890         }
891 
892         public SortedMap<K, V> tailMap(K startKey) {
893             synchronized (mutex) {
894                 return new SynchronizedSortedMap<K, V>(sm.tailMap(startKey),
895                         mutex);
896             }
897         }
898 
899         private void writeObject(ObjectOutputStream stream) throws IOException {
900             synchronized (mutex) {
901                 stream.defaultWriteObject();
902             }
903         }
904     }
905 
906     static class SynchronizedSortedSet<E> extends SynchronizedSet<E> implements
907             SortedSet<E> {
908         private static final long serialVersionUID = 8695801310862127406L;
909 
910         private final SortedSet<E> ss;
911 
912         SynchronizedSortedSet(SortedSet<E> set) {
913             super(set);
914             ss = set;
915         }
916 
917         SynchronizedSortedSet(SortedSet<E> set, Object mutex) {
918             super(set, mutex);
919             ss = set;
920         }
921 
922         public Comparator<? super E> comparator() {
923             synchronized (mutex) {
924                 return ss.comparator();
925             }
926         }
927 
928         public E first() {
929             synchronized (mutex) {
930                 return ss.first();
931             }
932         }
933 
934         public SortedSet<E> headSet(E end) {
935             synchronized (mutex) {
936                 return new SynchronizedSortedSet<E>(ss.headSet(end), mutex);
937             }
938         }
939 
940         public E last() {
941             synchronized (mutex) {
942                 return ss.last();
943             }
944         }
945 
946         public SortedSet<E> subSet(E start, E end) {
947             synchronized (mutex) {
948                 return new SynchronizedSortedSet<E>(ss.subSet(start, end),
949                         mutex);
950             }
951         }
952 
953         public SortedSet<E> tailSet(E start) {
954             synchronized (mutex) {
955                 return new SynchronizedSortedSet<E>(ss.tailSet(start), mutex);
956             }
957         }
958 
959         private void writeObject(ObjectOutputStream stream) throws IOException {
960             synchronized (mutex) {
961                 stream.defaultWriteObject();
962             }
963         }
964     }
965 
966     private static class UnmodifiableCollection<E> implements Collection<E>,
967             Serializable {
968         private static final long serialVersionUID = 1820017752578914078L;
969 
970         final Collection<E> c;
971 
972         UnmodifiableCollection(Collection<E> collection) {
973             c = collection;
974         }
975 
976         public boolean add(E object) {
977             throw new UnsupportedOperationException();
978         }
979 
980         public boolean addAll(Collection<? extends E> collection) {
981             throw new UnsupportedOperationException();
982         }
983 
984         public void clear() {
985             throw new UnsupportedOperationException();
986         }
987 
988         public boolean contains(Object object) {
989             return c.contains(object);
990         }
991 
992         public boolean containsAll(Collection<?> collection) {
993             return c.containsAll(collection);
994         }
995 
996         public boolean isEmpty() {
997             return c.isEmpty();
998         }
999 
1000         public Iterator<E> iterator() {
1001             return new Iterator<E>() {
1002                 Iterator<E> iterator = c.iterator();
1003 
1004                 public boolean hasNext() {
1005                     return iterator.hasNext();
1006                 }
1007 
1008                 public E next() {
1009                     return iterator.next();
1010                 }
1011 
1012                 public void remove() {
1013                     throw new UnsupportedOperationException();
1014                 }
1015             };
1016         }
1017 
1018         public boolean remove(Object object) {
1019             throw new UnsupportedOperationException();
1020         }
1021 
1022         public boolean removeAll(Collection<?> collection) {
1023             throw new UnsupportedOperationException();
1024         }
1025 
1026         public boolean retainAll(Collection<?> collection) {
1027             throw new UnsupportedOperationException();
1028         }
1029 
1030         public int size() {
1031             return c.size();
1032         }
1033 
1034         public Object[] toArray() {
1035             return c.toArray();
1036         }
1037 
1038         public <T> T[] toArray(T[] array) {
1039             return c.toArray(array);
1040         }
1041 
1042         @Override
1043         public String toString() {
1044             return c.toString();
1045         }
1046     }
1047 
1048     private static class UnmodifiableRandomAccessList<E> extends
1049             UnmodifiableList<E> implements RandomAccess {
1050         private static final long serialVersionUID = -2542308836966382001L;
1051 
1052         UnmodifiableRandomAccessList(List<E> l) {
1053             super(l);
1054         }
1055 
1056         @Override
1057         public List<E> subList(int start, int end) {
1058             return new UnmodifiableRandomAccessList<E>(list.subList(start, end));
1059         }
1060 
1061         /**
1062          * Replaces this UnmodifiableRandomAccessList with an UnmodifiableList
1063          * so that JREs before 1.4 can deserialize this object without any
1064          * problems. This is necessary since RandomAccess API was introduced
1065          * only in 1.4.
1066          * <p>
1067          *
1068          * @return UnmodifiableList
1069          *
1070          * @see UnmodifiableList#readResolve()
1071          */
1072         private Object writeReplace() {
1073             return new UnmodifiableList<E>(list);
1074         }
1075     }
1076 
1077     private static class UnmodifiableList<E> extends UnmodifiableCollection<E>
1078             implements List<E> {
1079         private static final long serialVersionUID = -283967356065247728L;
1080 
1081         final List<E> list;
1082 
1083         UnmodifiableList(List<E> l) {
1084             super(l);
1085             list = l;
1086         }
1087 
1088         public void add(int location, E object) {
1089             throw new UnsupportedOperationException();
1090         }
1091 
1092         public boolean addAll(int location, Collection<? extends E> collection) {
1093             throw new UnsupportedOperationException();
1094         }
1095 
1096         @Override
1097         public boolean equals(Object object) {
1098             return list.equals(object);
1099         }
1100 
1101         public E get(int location) {
1102             return list.get(location);
1103         }
1104 
1105         @Override
1106         public int hashCode() {
1107             return list.hashCode();
1108         }
1109 
1110         public int indexOf(Object object) {
1111             return list.indexOf(object);
1112         }
1113 
1114         public int lastIndexOf(Object object) {
1115             return list.lastIndexOf(object);
1116         }
1117 
1118         public ListIterator<E> listIterator() {
1119             return listIterator(0);
1120         }
1121 
1122         public ListIterator<E> listIterator(final int location) {
1123             return new ListIterator<E>() {
1124                 ListIterator<E> iterator = list.listIterator(location);
1125 
1126                 public void add(E object) {
1127                     throw new UnsupportedOperationException();
1128                 }
1129 
1130                 public boolean hasNext() {
1131                     return iterator.hasNext();
1132                 }
1133 
1134                 public boolean hasPrevious() {
1135                     return iterator.hasPrevious();
1136                 }
1137 
1138                 public E next() {
1139                     return iterator.next();
1140                 }
1141 
1142                 public int nextIndex() {
1143                     return iterator.nextIndex();
1144                 }
1145 
1146                 public E previous() {
1147                     return iterator.previous();
1148                 }
1149 
1150                 public int previousIndex() {
1151                     return iterator.previousIndex();
1152                 }
1153 
1154                 public void remove() {
1155                     throw new UnsupportedOperationException();
1156                 }
1157 
1158                 public void set(E object) {
1159                     throw new UnsupportedOperationException();
1160                 }
1161             };
1162         }
1163 
1164         public E remove(int location) {
1165             throw new UnsupportedOperationException();
1166         }
1167 
1168         public E set(int location, E object) {
1169             throw new UnsupportedOperationException();
1170         }
1171 
1172         public List<E> subList(int start, int end) {
1173             return new UnmodifiableList<E>(list.subList(start, end));
1174         }
1175 
1176         /**
1177          * Resolves UnmodifiableList instances to UnmodifiableRandomAccessList
1178          * instances if the underlying list is a Random Access list.
1179          * <p>
1180          * This is necessary since UnmodifiableRandomAccessList instances are
1181          * replaced with UnmodifiableList instances during serialization for
1182          * compliance with JREs before 1.4.
1183          * <p>
1184          *
1185          * @return an UnmodifiableList instance if the underlying list
1186          *         implements RandomAccess interface, or this same object if
1187          *         not.
1188          *
1189          * @see UnmodifiableRandomAccessList#writeReplace()
1190          */
1191         private Object readResolve() {
1192             if (list instanceof RandomAccess) {
1193                 return new UnmodifiableRandomAccessList<E>(list);
1194             }
1195             return this;
1196         }
1197     }
1198 
1199     private static class UnmodifiableMap<K, V> implements Map<K, V>,
1200             Serializable {
1201         private static final long serialVersionUID = -1034234728574286014L;
1202 
1203         private final Map<K, V> m;
1204 
1205         private static class UnmodifiableEntrySet<K, V> extends
1206                 UnmodifiableSet<Map.Entry<K, V>> {
1207             private static final long serialVersionUID = 7854390611657943733L;
1208 
1209             private static class UnmodifiableMapEntry<K, V> implements
1210                     Map.Entry<K, V> {
1211                 Map.Entry<K, V> mapEntry;
1212 
1213                 UnmodifiableMapEntry(Map.Entry<K, V> entry) {
1214                     mapEntry = entry;
1215                 }
1216 
1217                 @Override
1218                 public boolean equals(Object object) {
1219                     return mapEntry.equals(object);
1220                 }
1221 
1222                 public K getKey() {
1223                     return mapEntry.getKey();
1224                 }
1225 
1226                 public V getValue() {
1227                     return mapEntry.getValue();
1228                 }
1229 
1230                 @Override
1231                 public int hashCode() {
1232                     return mapEntry.hashCode();
1233                 }
1234 
1235                 public V setValue(V object) {
1236                     throw new UnsupportedOperationException();
1237                 }
1238 
1239                 @Override
1240                 public String toString() {
1241                     return mapEntry.toString();
1242                 }
1243             }
1244 
1245             UnmodifiableEntrySet(Set<Map.Entry<K, V>> set) {
1246                 super(set);
1247             }
1248 
1249             @Override
1250             public Iterator<Map.Entry<K, V>> iterator() {
1251                 return new Iterator<Map.Entry<K, V>>() {
1252                     Iterator<Map.Entry<K, V>> iterator = c.iterator();
1253 
1254                     public boolean hasNext() {
1255                         return iterator.hasNext();
1256                     }
1257 
1258                     public Map.Entry<K, V> next() {
1259                         return new UnmodifiableMapEntry<K, V>(iterator.next());
1260                     }
1261 
1262                     public void remove() {
1263                         throw new UnsupportedOperationException();
1264                     }
1265                 };
1266             }
1267 
1268             @Override
1269             public Object[] toArray() {
1270                 int length = c.size();
1271                 Object[] result = new Object[length];
1272                 Iterator<?> it = iterator();
1273                 for (int i = length; --i >= 0;) {
1274                     result[i] = it.next();
1275                 }
1276                 return result;
1277             }
1278 
1279             @Override
1280             @SuppressWarnings("unchecked")
1281             public <T> T[] toArray(T[] contents) {
1282                 int size = c.size(), index = 0;
1283                 Iterator<Map.Entry<K, V>> it = iterator();
1284                 if (size > contents.length) {
1285                     Class<?> ct = contents.getClass().getComponentType();
1286                     contents = (T[]) Array.newInstance(ct, size);
1287                 }
1288                 while (index < size) {
1289                     contents[index++] = (T) it.next();
1290                 }
1291                 if (index < contents.length) {
1292                     contents[index] = null;
1293                 }
1294                 return contents;
1295             }
1296         }
1297 
1298         UnmodifiableMap(Map<K, V> map) {
1299             m = map;
1300         }
1301 
1302         public void clear() {
1303             throw new UnsupportedOperationException();
1304         }
1305 
1306         public boolean containsKey(Object key) {
1307             return m.containsKey(key);
1308         }
1309 
1310         public boolean containsValue(Object value) {
1311             return m.containsValue(value);
1312         }
1313 
1314         public Set<Map.Entry<K, V>> entrySet() {
1315             return new UnmodifiableEntrySet<K, V>(m.entrySet());
1316         }
1317 
1318         @Override
1319         public boolean equals(Object object) {
1320             return m.equals(object);
1321         }
1322 
1323         public V get(Object key) {
1324             return m.get(key);
1325         }
1326 
1327         @Override
1328         public int hashCode() {
1329             return m.hashCode();
1330         }
1331 
1332         public boolean isEmpty() {
1333             return m.isEmpty();
1334         }
1335 
1336         public Set<K> keySet() {
1337             return new UnmodifiableSet<K>(m.keySet());
1338         }
1339 
1340         public V put(K key, V value) {
1341             throw new UnsupportedOperationException();
1342         }
1343 
1344         public void putAll(Map<? extends K, ? extends V> map) {
1345             throw new UnsupportedOperationException();
1346         }
1347 
1348         public V remove(Object key) {
1349             throw new UnsupportedOperationException();
1350         }
1351 
1352         public int size() {
1353             return m.size();
1354         }
1355 
1356         public Collection<V> values() {
1357             return new UnmodifiableCollection<V>(m.values());
1358         }
1359 
1360         @Override
1361         public String toString() {
1362             return m.toString();
1363         }
1364     }
1365 
1366     private static class UnmodifiableSet<E> extends UnmodifiableCollection<E>
1367             implements Set<E> {
1368         private static final long serialVersionUID = -9215047833775013803L;
1369 
1370         UnmodifiableSet(Set<E> set) {
1371             super(set);
1372         }
1373 
1374         @Override
1375         public boolean equals(Object object) {
1376             return c.equals(object);
1377         }
1378 
1379         @Override
1380         public int hashCode() {
1381             return c.hashCode();
1382         }
1383     }
1384 
1385     private static class UnmodifiableSortedMap<K, V> extends
1386             UnmodifiableMap<K, V> implements SortedMap<K, V> {
1387         private static final long serialVersionUID = -8806743815996713206L;
1388 
1389         private final SortedMap<K, V> sm;
1390 
1391         UnmodifiableSortedMap(SortedMap<K, V> map) {
1392             super(map);
1393             sm = map;
1394         }
1395 
1396         public Comparator<? super K> comparator() {
1397             return sm.comparator();
1398         }
1399 
1400         public K firstKey() {
1401             return sm.firstKey();
1402         }
1403 
1404         public SortedMap<K, V> headMap(K before) {
1405             return new UnmodifiableSortedMap<K, V>(sm.headMap(before));
1406         }
1407 
1408         public K lastKey() {
1409             return sm.lastKey();
1410         }
1411 
1412         public SortedMap<K, V> subMap(K start, K end) {
1413             return new UnmodifiableSortedMap<K, V>(sm.subMap(start, end));
1414         }
1415 
1416         public SortedMap<K, V> tailMap(K after) {
1417             return new UnmodifiableSortedMap<K, V>(sm.tailMap(after));
1418         }
1419     }
1420 
1421     private static class UnmodifiableSortedSet<E> extends UnmodifiableSet<E>
1422             implements SortedSet<E> {
1423         private static final long serialVersionUID = -4929149591599911165L;
1424 
1425         private final SortedSet<E> ss;
1426 
1427         UnmodifiableSortedSet(SortedSet<E> set) {
1428             super(set);
1429             ss = set;
1430         }
1431 
1432         public Comparator<? super E> comparator() {
1433             return ss.comparator();
1434         }
1435 
1436         public E first() {
1437             return ss.first();
1438         }
1439 
1440         public SortedSet<E> headSet(E before) {
1441             return new UnmodifiableSortedSet<E>(ss.headSet(before));
1442         }
1443 
1444         public E last() {
1445             return ss.last();
1446         }
1447 
1448         public SortedSet<E> subSet(E start, E end) {
1449             return new UnmodifiableSortedSet<E>(ss.subSet(start, end));
1450         }
1451 
1452         public SortedSet<E> tailSet(E after) {
1453             return new UnmodifiableSortedSet<E>(ss.tailSet(after));
1454         }
1455     }
1456 
1457     private Collections() {
1458         /* empty */
1459     }
1460 
1461     /**
1462      * Performs a binary search for the specified element in the specified
1463      * sorted list. The list needs to be already sorted in natural sorting
1464      * order. Searching in an unsorted array has an undefined result. It's also
1465      * undefined which element is found if there are multiple occurrences of the
1466      * same element.
1467      *
1468      * @param list
1469      *            the sorted list to search.
1470      * @param object
1471      *            the element to find.
1472      * @return the non-negative index of the element, or a negative index which
1473      *         is the {@code -index - 1} where the element would be inserted
1474      * @throws ClassCastException
1475      *             if an element in the List or the search element does not
1476      *             implement Comparable, or cannot be compared to each other.
1477      */
1478     @SuppressWarnings("unchecked")
1479     public static <T> int binarySearch(
1480             List<? extends Comparable<? super T>> list, T object) {
1481         if (list == null) {
1482             throw new NullPointerException();
1483         }
1484         if (list.isEmpty()) {
1485             return -1;
1486         }
1487 
1488 
1489         if (!(list instanceof RandomAccess)) {
1490             ListIterator<? extends Comparable<? super T>> it = list.listIterator();
1491             while (it.hasNext()) {
1492                 int result;
1493                 if ((result = -it.next().compareTo(object)) <= 0) {
1494                     if (result == 0) {
1495                         return it.previousIndex();
1496                     }
1497                     return -it.previousIndex() - 1;
1498                 }
1499             }
1500             return -list.size() - 1;
1501         }
1502 
1503         int low = 0, mid = list.size(), high = mid - 1, result = -1;
1504         while (low <= high) {
1505             mid = (low + high) >>> 1;
1506             if ((result = -list.get(mid).compareTo(object)) > 0) {
1507                 low = mid + 1;
1508             } else if (result == 0) {
1509                 return mid;
1510             } else {
1511                 high = mid - 1;
1512             }
1513         }
1514         return -mid - (result < 0 ? 1 : 2);
1515     }
1516 
1517     /**
1518      * Performs a binary search for the specified element in the specified
1519      * sorted list using the specified comparator. The list needs to be already
1520      * sorted according to the comparator passed. Searching in an unsorted array
1521      * has an undefined result. It's also undefined which element is found if
1522      * there are multiple occurrences of the same element.
1523      *
1524      * @param list
1525      *            the sorted List to search.
1526      * @param object
1527      *            the element to find.
1528      * @param comparator
1529      *            the comparator. If the comparator is {@code null} then the
1530      *            search uses the objects' natural ordering.
1531      * @return the non-negative index of the element, or a negative index which
1532      *         is the {@code -index - 1} where the element would be inserted.
1533      * @throws ClassCastException
1534      *             when an element in the list and the searched element cannot
1535      *             be compared to each other using the comparator.
1536      */
1537     @SuppressWarnings("unchecked")
1538     // BEGIN android-note
1539     // removed "@param <T> The element type", which is rejected by apicheck
1540     // END android-note
1541     public static <T> int binarySearch(List<? extends T> list, T object,
1542             Comparator<? super T> comparator) {
1543         if (comparator == null) {
1544             return Collections.binarySearch(
1545                     (List<? extends Comparable<? super T>>) list, object);
1546         }
1547         if (!(list instanceof RandomAccess)) {
1548             ListIterator<? extends T> it = list.listIterator();
1549             while (it.hasNext()) {
1550                 int result;
1551                 if ((result = -comparator.compare(it.next(), object)) <= 0) {
1552                     if (result == 0) {
1553                         return it.previousIndex();
1554                     }
1555                     return -it.previousIndex() - 1;
1556                 }
1557             }
1558             return -list.size() - 1;
1559         }
1560 
1561         int low = 0, mid = list.size(), high = mid - 1, result = -1;
1562         while (low <= high) {
1563             mid = (low + high) >>> 1;
1564             if ((result = -comparator.compare(list.get(mid),object)) > 0) {
1565                 low = mid + 1;
1566             } else if (result == 0) {
1567                 return mid;
1568             } else {
1569                 high = mid - 1;
1570             }
1571         }
1572         return -mid - (result < 0 ? 1 : 2);
1573     }
1574 
1575     /**
1576      * Copies the elements from the source list to the destination list. At the
1577      * end both lists will have the same objects at the same index. If the
1578      * destination array is larger than the source list, the elements in the
1579      * destination list with {@code index >= source.size()} will be unchanged.
1580      *
1581      * @param destination
1582      *            the list whose elements are set from the source list.
1583      * @param source
1584      *            the list with the elements to be copied into the destination.
1585      * @throws IndexOutOfBoundsException
1586      *             when the destination list is smaller than the source list.
1587      * @throws UnsupportedOperationException
1588      *             when replacing an element in the destination list is not
1589      *             supported.
1590      */
1591     public static <T> void copy(List<? super T> destination, List<? extends T> source) {
1592         if (destination.size() < source.size()) {
1593             throw new ArrayIndexOutOfBoundsException("Source size " + source.size() +
1594                     " does not fit into destination");
1595         }
1596         Iterator<? extends T> srcIt = source.iterator();
1597         ListIterator<? super T> destIt = destination.listIterator();
1598         while (srcIt.hasNext()) {
1599             try {
1600                 destIt.next();
1601             } catch (NoSuchElementException e) {
1602                 // TODO: AssertionError?
1603                 throw new ArrayIndexOutOfBoundsException("Source size " + source.size() +
1604                         " does not fit into destination");
1605             }
1606             destIt.set(srcIt.next());
1607         }
1608     }
1609 
1610     /**
1611      * Returns an {@code Enumeration} on the specified collection.
1612      *
1613      * @param collection
1614      *            the collection to enumerate.
1615      * @return an Enumeration.
1616      */
1617     public static <T> Enumeration<T> enumeration(Collection<T> collection) {
1618         final Collection<T> c = collection;
1619         return new Enumeration<T>() {
1620             Iterator<T> it = c.iterator();
1621 
1622             public boolean hasMoreElements() {
1623                 return it.hasNext();
1624             }
1625 
1626             public T nextElement() {
1627                 return it.next();
1628             }
1629         };
1630     }
1631 
1632     /**
1633      * Fills the specified list with the specified element.
1634      *
1635      * @param list
1636      *            the list to fill.
1637      * @param object
1638      *            the element to fill the list with.
1639      * @throws UnsupportedOperationException
1640      *             when replacing an element in the List is not supported.
1641      */
1642     public static <T> void fill(List<? super T> list, T object) {
1643         ListIterator<? super T> it = list.listIterator();
1644         while (it.hasNext()) {
1645             it.next();
1646             it.set(object);
1647         }
1648     }
1649 
1650     /**
1651      * Searches the specified collection for the maximum element.
1652      *
1653      * @param collection
1654      *            the collection to search.
1655      * @return the maximum element in the Collection.
1656      * @throws ClassCastException
1657      *             when an element in the collection does not implement
1658      *             {@code Comparable} or elements cannot be compared to each
1659      *             other.
1660      */
1661     public static <T extends Object & Comparable<? super T>> T max(
1662             Collection<? extends T> collection) {
1663         Iterator<? extends T> it = collection.iterator();
1664         T max = it.next();
1665         while (it.hasNext()) {
1666             T next = it.next();
1667             if (max.compareTo(next) < 0) {
1668                 max = next;
1669             }
1670         }
1671         return max;
1672     }
1673 
1674     /**
1675      * Searches the specified collection for the maximum element using the
1676      * specified comparator.
1677      *
1678      * @param collection
1679      *            the collection to search.
1680      * @param comparator
1681      *            the comparator.
1682      * @return the maximum element in the Collection.
1683      * @throws ClassCastException
1684      *             when elements in the collection cannot be compared to each
1685      *             other using the {@code Comparator}.
1686      */
1687     public static <T> T max(Collection<? extends T> collection,
1688             Comparator<? super T> comparator) {
1689         if (comparator == null) {
1690             @SuppressWarnings("unchecked") // null comparator? T is comparable
1691             T result = (T) max((Collection<Comparable>) collection);
1692             return result;
1693         }
1694 
1695         Iterator<? extends T> it = collection.iterator();
1696         T max = it.next();
1697         while (it.hasNext()) {
1698             T next = it.next();
1699             if (comparator.compare(max, next) < 0) {
1700                 max = next;
1701             }
1702         }
1703         return max;
1704     }
1705 
1706     /**
1707      * Searches the specified collection for the minimum element.
1708      *
1709      * @param collection
1710      *            the collection to search.
1711      * @return the minimum element in the collection.
1712      * @throws ClassCastException
1713      *             when an element in the collection does not implement
1714      *             {@code Comparable} or elements cannot be compared to each
1715      *             other.
1716      */
1717     public static <T extends Object & Comparable<? super T>> T min(
1718             Collection<? extends T> collection) {
1719         Iterator<? extends T> it = collection.iterator();
1720         T min = it.next();
1721         while (it.hasNext()) {
1722             T next = it.next();
1723             if (min.compareTo(next) > 0) {
1724                 min = next;
1725             }
1726         }
1727         return min;
1728     }
1729 
1730     /**
1731      * Searches the specified collection for the minimum element using the
1732      * specified comparator.
1733      *
1734      * @param collection
1735      *            the collection to search.
1736      * @param comparator
1737      *            the comparator.
1738      * @return the minimum element in the collection.
1739      * @throws ClassCastException
1740      *             when elements in the collection cannot be compared to each
1741      *             other using the {@code Comparator}.
1742      */
1743     public static <T> T min(Collection<? extends T> collection,
1744             Comparator<? super T> comparator) {
1745         if (comparator == null) {
1746             @SuppressWarnings("unchecked") // null comparator? T is comparable
1747             T result = (T) min((Collection<Comparable>) collection);
1748             return result;
1749         }
1750 
1751         Iterator<? extends T> it = collection.iterator();
1752         T min = it.next();
1753         while (it.hasNext()) {
1754             T next = it.next();
1755             if (comparator.compare(min, next) > 0) {
1756                 min = next;
1757             }
1758         }
1759         return min;
1760     }
1761 
1762     /**
1763      * Returns a list containing the specified number of the specified element.
1764      * The list cannot be modified. The list is serializable.
1765      *
1766      * @param length
1767      *            the size of the returned list.
1768      * @param object
1769      *            the element to be added {@code length} times to a list.
1770      * @return a list containing {@code length} copies of the element.
1771      * @throws IllegalArgumentException
1772      *             when {@code length < 0}.
1773      */
1774     public static <T> List<T> nCopies(final int length, T object) {
1775         return new CopiesList<T>(length, object);
1776     }
1777 
1778     /**
1779      * Modifies the specified {@code List} by reversing the order of the
1780      * elements.
1781      *
1782      * @param list
1783      *            the list to reverse.
1784      * @throws UnsupportedOperationException
1785      *             when replacing an element in the List is not supported.
1786      */
1787     @SuppressWarnings("unchecked")
1788     public static void reverse(List<?> list) {
1789         int size = list.size();
1790         ListIterator<Object> front = (ListIterator<Object>) list.listIterator();
1791         ListIterator<Object> back = (ListIterator<Object>) list
1792                 .listIterator(size);
1793         for (int i = 0; i < size / 2; i++) {
1794             Object frontNext = front.next();
1795             Object backPrev = back.previous();
1796             front.set(backPrev);
1797             back.set(frontNext);
1798         }
1799     }
1800 
1801     /**
1802      * A comparator which reverses the natural order of the elements. The
1803      * {@code Comparator} that's returned is {@link Serializable}.
1804      *
1805      * @return a {@code Comparator} instance.
1806      * @see Comparator
1807      * @see Comparable
1808      * @see Serializable
1809      */
1810     @SuppressWarnings("unchecked")
1811     public static <T> Comparator<T> reverseOrder() {
1812         return (Comparator) ReverseComparator.INSTANCE;
1813     }
1814 
1815     /**
1816      * Returns a {@link Comparator} that reverses the order of the
1817      * {@code Comparator} passed. If the {@code Comparator} passed is
1818      * {@code null}, then this method is equivalent to {@link #reverseOrder()}.
1819      * <p>
1820      * The {@code Comparator} that's returned is {@link Serializable} if the
1821      * {@code Comparator} passed is serializable or {@code null}.
1822      *
1823      * @param c
1824      *            the {@code Comparator} to reverse or {@code null}.
1825      * @return a {@code Comparator} instance.
1826      * @see Comparator
1827      * @since 1.5
1828      */
1829     public static <T> Comparator<T> reverseOrder(Comparator<T> c) {
1830         if (c == null) {
1831             return reverseOrder();
1832         }
1833         if (c instanceof ReverseComparator2) {
1834             return ((ReverseComparator2<T>) c).cmp;
1835         }
1836         return new ReverseComparator2<T>(c);
1837     }
1838 
1839     /**
1840      * Moves every element of the list to a random new position in the list.
1841      *
1842      * @param list
1843      *            the List to shuffle.
1844      *
1845      * @throws UnsupportedOperationException
1846      *             when replacing an element in the List is not supported.
1847      */
1848     public static void shuffle(List<?> list) {
1849         shuffle(list, new Random());
1850     }
1851 
1852     /**
1853      * Moves every element of the list to a random new position in the list
1854      * using the specified random number generator.
1855      *
1856      * @param list
1857      *            the list to shuffle.
1858      * @param random
1859      *            the random number generator.
1860      * @throws UnsupportedOperationException
1861      *             when replacing an element in the list is not supported.
1862      */
1863     public static void shuffle(List<?> list, Random random) {
1864         @SuppressWarnings("unchecked") // we won't put foreign objects in
1865         final List<Object> objectList = (List<Object>) list;
1866 
1867         if (list instanceof RandomAccess) {
1868             for (int i = objectList.size() - 1; i > 0; i--) {
1869                 int index = random.nextInt(i + 1);
1870                 objectList.set(index, objectList.set(i, objectList.get(index)));
1871             }
1872         } else {
1873             Object[] array = objectList.toArray();
1874             for (int i = array.length - 1; i > 0; i--) {
1875                 int index = random.nextInt(i + 1);
1876                 Object temp = array[i];
1877                 array[i] = array[index];
1878                 array[index] = temp;
1879             }
1880 
1881             int i = 0;
1882             ListIterator<Object> it = objectList.listIterator();
1883             while (it.hasNext()) {
1884                 it.next();
1885                 it.set(array[i++]);
1886             }
1887         }
1888     }
1889 
1890     /**
1891      * Returns a set containing the specified element. The set cannot be
1892      * modified. The set is serializable.
1893      *
1894      * @param object
1895      *            the element.
1896      * @return a set containing the element.
1897      */
1898     public static <E> Set<E> singleton(E object) {
1899         return new SingletonSet<E>(object);
1900     }
1901 
1902     /**
1903      * Returns a list containing the specified element. The list cannot be
1904      * modified. The list is serializable.
1905      *
1906      * @param object
1907      *            the element.
1908      * @return a list containing the element.
1909      */
1910     public static <E> List<E> singletonList(E object) {
1911         return new SingletonList<E>(object);
1912     }
1913 
1914     /**
1915      * Returns a Map containing the specified key and value. The map cannot be
1916      * modified. The map is serializable.
1917      *
1918      * @param key
1919      *            the key.
1920      * @param value
1921      *            the value.
1922      * @return a Map containing the key and value.
1923      */
1924     public static <K, V> Map<K, V> singletonMap(K key, V value) {
1925         return new SingletonMap<K, V>(key, value);
1926     }
1927 
1928     /**
1929      * Sorts the specified list in ascending natural order. The algorithm is
1930      * stable which means equal elements don't get reordered.
1931      *
1932      * @param list
1933      *            the list to be sorted.
1934      * @throws ClassCastException
1935      *             when an element in the List does not implement Comparable or
1936      *             elements cannot be compared to each other.
1937      */
1938     @SuppressWarnings("unchecked")
1939     public static <T extends Comparable<? super T>> void sort(List<T> list) {
1940         Object[] array = list.toArray();
1941         Arrays.sort(array);
1942         int i = 0;
1943         ListIterator<T> it = list.listIterator();
1944         while (it.hasNext()) {
1945             it.next();
1946             it.set((T) array[i++]);
1947         }
1948     }
1949 
1950     /**
1951      * Sorts the specified list using the specified comparator. The algorithm is
1952      * stable which means equal elements don't get reordered.
1953      *
1954      * @param list
1955      *            the list to be sorted.
1956      * @param comparator
1957      *            the comparator.
1958      * @throws ClassCastException
1959      *             when elements in the list cannot be compared to each other
1960      *             using the comparator.
1961      */
1962     @SuppressWarnings("unchecked")
1963     public static <T> void sort(List<T> list, Comparator<? super T> comparator) {
1964         T[] array = list.toArray((T[]) new Object[list.size()]);
1965         Arrays.sort(array, comparator);
1966         int i = 0;
1967         ListIterator<T> it = list.listIterator();
1968         while (it.hasNext()) {
1969             it.next();
1970             it.set(array[i++]);
1971         }
1972     }
1973 
1974     /**
1975      * Swaps the elements of list {@code list} at indices {@code index1} and
1976      * {@code index2}.
1977      *
1978      * @param list
1979      *            the list to manipulate.
1980      * @param index1
1981      *            position of the first element to swap with the element in
1982      *            index2.
1983      * @param index2
1984      *            position of the other element.
1985      *
1986      * @throws IndexOutOfBoundsException
1987      *             if index1 or index2 is out of range of this list.
1988      * @since 1.4
1989      */
1990     @SuppressWarnings("unchecked")
1991     public static void swap(List<?> list, int index1, int index2) {
1992         if (list == null) {
1993             throw new NullPointerException();
1994         }
1995         final int size = list.size();
1996         if (index1 < 0 || index1 >= size || index2 < 0 || index2 >= size) {
1997             throw new IndexOutOfBoundsException();
1998         }
1999         if (index1 == index2) {
2000             return;
2001         }
2002         List<Object> rawList = (List<Object>) list;
2003         rawList.set(index2, rawList.set(index1, rawList.get(index2)));
2004     }
2005 
2006     /**
2007      * Replaces all occurrences of Object {@code obj} in {@code list} with
2008      * {@code newObj}. If the {@code obj} is {@code null}, then all
2009      * occurrences of {@code null} are replaced with {@code newObj}.
2010      *
2011      * @param list
2012      *            the list to modify.
2013      * @param obj
2014      *            the object to find and replace occurrences of.
2015      * @param obj2
2016      *            the object to replace all occurrences of {@code obj} in
2017      *            {@code list}.
2018      * @return true, if at least one occurrence of {@code obj} has been found in
2019      *         {@code list}.
2020      * @throws UnsupportedOperationException
2021      *             if the list does not support setting elements.
2022      */
2023     public static <T> boolean replaceAll(List<T> list, T obj, T obj2) {
2024         int index;
2025         boolean found = false;
2026 
2027         while ((index = list.indexOf(obj)) > -1) {
2028             found = true;
2029             list.set(index, obj2);
2030         }
2031         return found;
2032     }
2033 
2034     /**
2035      * Rotates the elements in {@code list} by the distance {@code dist}
2036      * <p>
2037      * e.g. for a given list with elements [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
2038      * calling rotate(list, 3) or rotate(list, -7) would modify the list to look
2039      * like this: [8, 9, 0, 1, 2, 3, 4, 5, 6, 7]
2040      *
2041      * @param lst
2042      *            the list whose elements are to be rotated.
2043      * @param dist
2044      *            is the distance the list is rotated. This can be any valid
2045      *            integer. Negative values rotate the list backwards.
2046      */
2047     @SuppressWarnings("unchecked")
2048     public static void rotate(List<?> lst, int dist) {
2049         List<Object> list = (List<Object>) lst;
2050         int size = list.size();
2051 
2052         // Can't sensibly rotate an empty collection
2053         if (size == 0) {
2054             return;
2055         }
2056 
2057         // normalize the distance
2058         int normdist;
2059         if (dist > 0) {
2060             normdist = dist % size;
2061         } else {
2062             normdist = size - ((dist % size) * (-1));
2063         }
2064 
2065         if (normdist == 0 || normdist == size) {
2066             return;
2067         }
2068 
2069         if (list instanceof RandomAccess) {
2070             // make sure each element gets juggled
2071             // with the element in the position it is supposed to go to
2072             Object temp = list.get(0);
2073             int index = 0, beginIndex = 0;
2074             for (int i = 0; i < size; i++) {
2075                 index = (index + normdist) % size;
2076                 temp = list.set(index, temp);
2077                 if (index == beginIndex) {
2078                     index = ++beginIndex;
2079                     temp = list.get(beginIndex);
2080                 }
2081             }
2082         } else {
2083             int divideIndex = (size - normdist) % size;
2084             List<Object> sublist1 = list.subList(0, divideIndex);
2085             List<Object> sublist2 = list.subList(divideIndex, size);
2086             reverse(sublist1);
2087             reverse(sublist2);
2088             reverse(list);
2089         }
2090     }
2091 
2092     /**
2093      * Searches the {@code list} for {@code sublist} and returns the beginning
2094      * index of the first occurrence.
2095      * <p>
2096      * -1 is returned if the {@code sublist} does not exist in {@code list}.
2097      *
2098      * @param list
2099      *            the List to search {@code sublist} in.
2100      * @param sublist
2101      *            the List to search in {@code list}.
2102      * @return the beginning index of the first occurrence of {@code sublist} in
2103      *         {@code list}, or -1.
2104      */
2105     public static int indexOfSubList(List<?> list, List<?> sublist) {
2106         int size = list.size();
2107         int sublistSize = sublist.size();
2108 
2109         if (sublistSize > size) {
2110             return -1;
2111         }
2112 
2113         if (sublistSize == 0) {
2114             return 0;
2115         }
2116 
2117         // find the first element of sublist in the list to get a head start
2118         Object firstObj = sublist.get(0);
2119         int index = list.indexOf(firstObj);
2120         if (index == -1) {
2121             return -1;
2122         }
2123 
2124         while (index < size && (size - index >= sublistSize)) {
2125             ListIterator<?> listIt = list.listIterator(index);
2126 
2127             if ((firstObj == null) ? listIt.next() == null : firstObj
2128                     .equals(listIt.next())) {
2129 
2130                 // iterate through the elements in sublist to see
2131                 // if they are included in the same order in the list
2132                 ListIterator<?> sublistIt = sublist.listIterator(1);
2133                 boolean difFound = false;
2134                 while (sublistIt.hasNext()) {
2135                     Object element = sublistIt.next();
2136                     if (!listIt.hasNext()) {
2137                         return -1;
2138                     }
2139                     if ((element == null) ? listIt.next() != null : !element
2140                             .equals(listIt.next())) {
2141                         difFound = true;
2142                         break;
2143                     }
2144                 }
2145                 // All elements of sublist are found in main list
2146                 // starting from index.
2147                 if (!difFound) {
2148                     return index;
2149                 }
2150             }
2151             // This was not the sequence we were looking for,
2152             // continue search for the firstObj in main list
2153             // at the position after index.
2154             index++;
2155         }
2156         return -1;
2157     }
2158 
2159     /**
2160      * Searches the {@code list} for {@code sublist} and returns the beginning
2161      * index of the last occurrence.
2162      * <p>
2163      * -1 is returned if the {@code sublist} does not exist in {@code list}.
2164      *
2165      * @param list
2166      *            the list to search {@code sublist} in.
2167      * @param sublist
2168      *            the list to search in {@code list}.
2169      * @return the beginning index of the last occurrence of {@code sublist} in
2170      *         {@code list}, or -1.
2171      */
2172     public static int lastIndexOfSubList(List<?> list, List<?> sublist) {
2173         int sublistSize = sublist.size();
2174         int size = list.size();
2175 
2176         if (sublistSize > size) {
2177             return -1;
2178         }
2179 
2180         if (sublistSize == 0) {
2181             return size;
2182         }
2183 
2184         // find the last element of sublist in the list to get a head start
2185         Object lastObj = sublist.get(sublistSize - 1);
2186         int index = list.lastIndexOf(lastObj);
2187 
2188         while ((index > -1) && (index + 1 >= sublistSize)) {
2189             ListIterator<?> listIt = list.listIterator(index + 1);
2190 
2191             if ((lastObj == null) ? listIt.previous() == null : lastObj
2192                     .equals(listIt.previous())) {
2193                 // iterate through the elements in sublist to see
2194                 // if they are included in the same order in the list
2195                 ListIterator<?> sublistIt = sublist
2196                         .listIterator(sublistSize - 1);
2197                 boolean difFound = false;
2198                 while (sublistIt.hasPrevious()) {
2199                     Object element = sublistIt.previous();
2200                     if (!listIt.hasPrevious()) {
2201                         return -1;
2202                     }
2203                     if ((element == null) ? listIt.previous() != null
2204                             : !element.equals(listIt.previous())) {
2205                         difFound = true;
2206                         break;
2207                     }
2208                 }
2209                 // All elements of sublist are found in main list
2210                 // starting from listIt.nextIndex().
2211                 if (!difFound) {
2212                     return listIt.nextIndex();
2213                 }
2214             }
2215             // This was not the sequence we were looking for,
2216             // continue search for the lastObj in main list
2217             // at the position before index.
2218             index--;
2219         }
2220         return -1;
2221     }
2222 
2223     /**
2224      * Returns an {@code ArrayList} with all the elements in the {@code
2225      * enumeration}. The elements in the returned {@code ArrayList} are in the
2226      * same order as in the {@code enumeration}.
2227      *
2228      * @param enumeration
2229      *            the source {@link Enumeration}.
2230      * @return an {@code ArrayList} from {@code enumeration}.
2231      */
2232     public static <T> ArrayList<T> list(Enumeration<T> enumeration) {
2233         ArrayList<T> list = new ArrayList<T>();
2234         while (enumeration.hasMoreElements()) {
2235             list.add(enumeration.nextElement());
2236         }
2237         return list;
2238     }
2239 
2240     /**
2241      * Returns a wrapper on the specified collection which synchronizes all
2242      * access to the collection.
2243      *
2244      * @param collection
2245      *            the Collection to wrap in a synchronized collection.
2246      * @return a synchronized Collection.
2247      */
2248     public static <T> Collection<T> synchronizedCollection(
2249             Collection<T> collection) {
2250         if (collection == null) {
2251             throw new NullPointerException();
2252         }
2253         return new SynchronizedCollection<T>(collection);
2254     }
2255 
2256     /**
2257      * Returns a wrapper on the specified List which synchronizes all access to
2258      * the List.
2259      *
2260      * @param list
2261      *            the List to wrap in a synchronized list.
2262      * @return a synchronized List.
2263      */
2264     public static <T> List<T> synchronizedList(List<T> list) {
2265         if (list == null) {
2266             throw new NullPointerException();
2267         }
2268         if (list instanceof RandomAccess) {
2269             return new SynchronizedRandomAccessList<T>(list);
2270         }
2271         return new SynchronizedList<T>(list);
2272     }
2273 
2274     /**
2275      * Returns a wrapper on the specified map which synchronizes all access to
2276      * the map.
2277      *
2278      * @param map
2279      *            the map to wrap in a synchronized map.
2280      * @return a synchronized Map.
2281      */
2282     public static <K, V> Map<K, V> synchronizedMap(Map<K, V> map) {
2283         if (map == null) {
2284             throw new NullPointerException();
2285         }
2286         return new SynchronizedMap<K, V>(map);
2287     }
2288 
2289     /**
2290      * Returns a wrapper on the specified set which synchronizes all access to
2291      * the set.
2292      *
2293      * @param set
2294      *            the set to wrap in a synchronized set.
2295      * @return a synchronized set.
2296      */
2297     public static <E> Set<E> synchronizedSet(Set<E> set) {
2298         if (set == null) {
2299             throw new NullPointerException();
2300         }
2301         return new SynchronizedSet<E>(set);
2302     }
2303 
2304     /**
2305      * Returns a wrapper on the specified sorted map which synchronizes all
2306      * access to the sorted map.
2307      *
2308      * @param map
2309      *            the sorted map to wrap in a synchronized sorted map.
2310      * @return a synchronized sorted map.
2311      */
2312     public static <K, V> SortedMap<K, V> synchronizedSortedMap(
2313             SortedMap<K, V> map) {
2314         if (map == null) {
2315             throw new NullPointerException();
2316         }
2317         return new SynchronizedSortedMap<K, V>(map);
2318     }
2319 
2320     /**
2321      * Returns a wrapper on the specified sorted set which synchronizes all
2322      * access to the sorted set.
2323      *
2324      * @param set
2325      *            the sorted set to wrap in a synchronized sorted set.
2326      * @return a synchronized sorted set.
2327      */
2328     public static <E> SortedSet<E> synchronizedSortedSet(SortedSet<E> set) {
2329         if (set == null) {
2330             throw new NullPointerException();
2331         }
2332         return new SynchronizedSortedSet<E>(set);
2333     }
2334 
2335     /**
2336      * Returns a wrapper on the specified collection which throws an
2337      * {@code UnsupportedOperationException} whenever an attempt is made to
2338      * modify the collection.
2339      *
2340      * @param collection
2341      *            the collection to wrap in an unmodifiable collection.
2342      * @return an unmodifiable collection.
2343      */
2344     @SuppressWarnings("unchecked")
2345     public static <E> Collection<E> unmodifiableCollection(
2346             Collection<? extends E> collection) {
2347         if (collection == null) {
2348             throw new NullPointerException();
2349         }
2350         return new UnmodifiableCollection<E>((Collection<E>) collection);
2351     }
2352 
2353     /**
2354      * Returns a wrapper on the specified list which throws an
2355      * {@code UnsupportedOperationException} whenever an attempt is made to
2356      * modify the list.
2357      *
2358      * @param list
2359      *            the list to wrap in an unmodifiable list.
2360      * @return an unmodifiable List.
2361      */
2362     @SuppressWarnings("unchecked")
2363     public static <E> List<E> unmodifiableList(List<? extends E> list) {
2364         if (list == null) {
2365             throw new NullPointerException();
2366         }
2367         if (list instanceof RandomAccess) {
2368             return new UnmodifiableRandomAccessList<E>((List<E>) list);
2369         }
2370         return new UnmodifiableList<E>((List<E>) list);
2371     }
2372 
2373     /**
2374      * Returns a wrapper on the specified map which throws an
2375      * {@code UnsupportedOperationException} whenever an attempt is made to
2376      * modify the map.
2377      *
2378      * @param map
2379      *            the map to wrap in an unmodifiable map.
2380      * @return a unmodifiable map.
2381      */
2382     @SuppressWarnings("unchecked")
2383     public static <K, V> Map<K, V> unmodifiableMap(
2384             Map<? extends K, ? extends V> map) {
2385         if (map == null) {
2386             throw new NullPointerException();
2387         }
2388         return new UnmodifiableMap<K, V>((Map<K, V>) map);
2389     }
2390 
2391     /**
2392      * Returns a wrapper on the specified set which throws an
2393      * {@code UnsupportedOperationException} whenever an attempt is made to
2394      * modify the set.
2395      *
2396      * @param set
2397      *            the set to wrap in an unmodifiable set.
2398      * @return a unmodifiable set
2399      */
2400     @SuppressWarnings("unchecked")
2401     public static <E> Set<E> unmodifiableSet(Set<? extends E> set) {
2402         if (set == null) {
2403             throw new NullPointerException();
2404         }
2405         return new UnmodifiableSet<E>((Set<E>) set);
2406     }
2407 
2408     /**
2409      * Returns a wrapper on the specified sorted map which throws an
2410      * {@code UnsupportedOperationException} whenever an attempt is made to
2411      * modify the sorted map.
2412      *
2413      * @param map
2414      *            the sorted map to wrap in an unmodifiable sorted map.
2415      * @return a unmodifiable sorted map
2416      */
2417     @SuppressWarnings("unchecked")
2418     public static <K, V> SortedMap<K, V> unmodifiableSortedMap(
2419             SortedMap<K, ? extends V> map) {
2420         if (map == null) {
2421             throw new NullPointerException();
2422         }
2423         return new UnmodifiableSortedMap<K, V>((SortedMap<K, V>) map);
2424     }
2425 
2426     /**
2427      * Returns a wrapper on the specified sorted set which throws an
2428      * {@code UnsupportedOperationException} whenever an attempt is made to
2429      * modify the sorted set.
2430      *
2431      * @param set
2432      *            the sorted set to wrap in an unmodifiable sorted set.
2433      * @return a unmodifiable sorted set.
2434      */
2435     public static <E> SortedSet<E> unmodifiableSortedSet(SortedSet<E> set) {
2436         if (set == null) {
2437             throw new NullPointerException();
2438         }
2439         return new UnmodifiableSortedSet<E>(set);
2440     }
2441 
2442     /**
2443      * Returns the number of elements in the {@code Collection} that match the
2444      * {@code Object} passed. If the {@code Object} is {@code null}, then the
2445      * number of {@code null} elements is returned.
2446      *
2447      * @param c
2448      *            the {@code Collection} to search.
2449      * @param o
2450      *            the {@code Object} to search for.
2451      * @return the number of matching elements.
2452      * @throws NullPointerException
2453      *             if the {@code Collection} parameter is {@code null}.
2454      * @since 1.5
2455      */
2456     public static int frequency(Collection<?> c, Object o) {
2457         if (c == null) {
2458             throw new NullPointerException();
2459         }
2460         if (c.isEmpty()) {
2461             return 0;
2462         }
2463         int result = 0;
2464         Iterator<?> itr = c.iterator();
2465         while (itr.hasNext()) {
2466             Object e = itr.next();
2467             if (o == null ? e == null : o.equals(e)) {
2468                 result++;
2469             }
2470         }
2471         return result;
2472     }
2473 
2474     /**
2475      * Returns a type-safe empty, immutable {@link List}.
2476      *
2477      * @return an empty {@link List}.
2478      * @since 1.5
2479      * @see #EMPTY_LIST
2480      */
2481     @SuppressWarnings("unchecked")
2482     public static final <T> List<T> emptyList() {
2483         return EMPTY_LIST;
2484     }
2485 
2486     /**
2487      * Returns a type-safe empty, immutable {@link Set}.
2488      *
2489      * @return an empty {@link Set}.
2490      * @since 1.5
2491      * @see #EMPTY_SET
2492      */
2493     @SuppressWarnings("unchecked")
2494     public static final <T> Set<T> emptySet() {
2495         return EMPTY_SET;
2496     }
2497 
2498     /**
2499      * Returns a type-safe empty, immutable {@link Map}.
2500      *
2501      * @return an empty {@link Map}.
2502      * @since 1.5
2503      * @see #EMPTY_MAP
2504      */
2505     @SuppressWarnings("unchecked")
2506     public static final <K, V> Map<K, V> emptyMap() {
2507         return EMPTY_MAP;
2508     }
2509 
2510     /**
2511      * Returns a dynamically typesafe view of the specified collection. Trying
2512      * to insert an element of the wrong type into this collection throws a
2513      * {@code ClassCastException}. At creation time the types in {@code c} are
2514      * not checked for correct type.
2515      *
2516      * @param c
2517      *            the collection to be wrapped in a typesafe collection.
2518      * @param type
2519      *            the type of the elements permitted to insert.
2520      * @return a typesafe collection.
2521      */
2522     public static <E> Collection<E> checkedCollection(Collection<E> c,
2523             Class<E> type) {
2524         return new CheckedCollection<E>(c, type);
2525     }
2526 
2527     /**
2528      * Returns a dynamically typesafe view of the specified map. Trying to
2529      * insert an element of the wrong type into this map throws a
2530      * {@code ClassCastException}. At creation time the types in {@code m} are
2531      * not checked for correct type.
2532      *
2533      * @param m
2534      *            the map to be wrapped in a typesafe map.
2535      * @param keyType
2536      *            the type of the keys permitted to insert.
2537      * @param valueType
2538      *            the type of the values permitted to insert.
2539      * @return a typesafe map.
2540      */
2541     public static <K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType,
2542             Class<V> valueType) {
2543         return new CheckedMap<K, V>(m, keyType, valueType);
2544     }
2545 
2546     /**
2547      * Returns a dynamically typesafe view of the specified list. Trying to
2548      * insert an element of the wrong type into this list throws a
2549      * {@code ClassCastException}. At creation time the types in {@code list}
2550      * are not checked for correct type.
2551      *
2552      * @param list
2553      *            the list to be wrapped in a typesafe list.
2554      * @param type
2555      *            the type of the elements permitted to insert.
2556      * @return a typesafe list.
2557      */
2558     public static <E> List<E> checkedList(List<E> list, Class<E> type) {
2559         if (list instanceof RandomAccess) {
2560             return new CheckedRandomAccessList<E>(list, type);
2561         }
2562         return new CheckedList<E>(list, type);
2563     }
2564 
2565     /**
2566      * Returns a dynamically typesafe view of the specified set. Trying to
2567      * insert an element of the wrong type into this set throws a
2568      * {@code ClassCastException}. At creation time the types in {@code s} are
2569      * not checked for correct type.
2570      *
2571      * @param s
2572      *            the set to be wrapped in a typesafe set.
2573      * @param type
2574      *            the type of the elements permitted to insert.
2575      * @return a typesafe set.
2576      */
2577     public static <E> Set<E> checkedSet(Set<E> s, Class<E> type) {
2578         return new CheckedSet<E>(s, type);
2579     }
2580 
2581     /**
2582      * Returns a dynamically typesafe view of the specified sorted map. Trying
2583      * to insert an element of the wrong type into this sorted map throws a
2584      * {@code ClassCastException}. At creation time the types in {@code m} are
2585      * not checked for correct type.
2586      *
2587      * @param m
2588      *            the sorted map to be wrapped in a typesafe sorted map.
2589      * @param keyType
2590      *            the type of the keys permitted to insert.
2591      * @param valueType
2592      *            the type of the values permitted to insert.
2593      * @return a typesafe sorted map.
2594      */
2595     public static <K, V> SortedMap<K, V> checkedSortedMap(SortedMap<K, V> m,
2596             Class<K> keyType, Class<V> valueType) {
2597         return new CheckedSortedMap<K, V>(m, keyType, valueType);
2598     }
2599 
2600     /**
2601      * Returns a dynamically typesafe view of the specified sorted set. Trying
2602      * to insert an element of the wrong type into this sorted set throws a
2603      * {@code ClassCastException}. At creation time the types in {@code s} are
2604      * not checked for correct type.
2605      *
2606      * @param s
2607      *            the sorted set to be wrapped in a typesafe sorted set.
2608      * @param type
2609      *            the type of the elements permitted to insert.
2610      * @return a typesafe sorted set.
2611      */
2612     public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,
2613             Class<E> type) {
2614         return new CheckedSortedSet<E>(s, type);
2615     }
2616 
2617     /**
2618      * Adds all the specified elements to the specified collection.
2619      *
2620      * @param c
2621      *            the collection the elements are to be inserted into.
2622      * @param a
2623      *            the elements to insert.
2624      * @return true if the collection changed during insertion.
2625      * @throws UnsupportedOperationException
2626      *             when the method is not supported.
2627      * @throws NullPointerException
2628      *             when {@code c} or {@code a} is {@code null}, or {@code a}
2629      *             contains one or more {@code null} elements and {@code c}
2630      *             doesn't support {@code null} elements.
2631      * @throws IllegalArgumentException
2632      *             if at least one of the elements can't be inserted into the
2633      *             collection.
2634      */
2635     public static <T> boolean addAll(Collection<? super T> c, T... a) {
2636         boolean modified = false;
2637         for (int i = 0; i < a.length; i++) {
2638             modified |= c.add(a[i]);
2639         }
2640         return modified;
2641     }
2642 
2643     /**
2644      * Returns whether the specified collections have no elements in common.
2645      *
2646      * @param c1
2647      *            the first collection.
2648      * @param c2
2649      *            the second collection.
2650      * @return {@code true} if the collections have no elements in common,
2651      *         {@code false} otherwise.
2652      * @throws NullPointerException
2653      *             if one of the collections is {@code null}.
2654      */
2655     public static boolean disjoint(Collection<?> c1, Collection<?> c2) {
2656         if ((c1 instanceof Set) && !(c2 instanceof Set)
2657                 || (c2.size()) > c1.size()) {
2658             Collection<?> tmp = c1;
2659             c1 = c2;
2660             c2 = tmp;
2661         }
2662         Iterator<?> it = c1.iterator();
2663         while (it.hasNext()) {
2664             if (c2.contains(it.next())) {
2665                 return false;
2666             }
2667         }
2668         return true;
2669     }
2670 
2671     /**
2672      * Checks if specified object is instance of specified class. Used for a
2673      * dynamically typesafe view of the collections.
2674      *
2675      * @param obj -
2676      *            object is to be checked
2677      * @param type -
2678      *            class of object that should be
2679      * @return specified object
2680      */
2681     static <E> E checkType(E obj, Class<? extends E> type) {
2682         if (obj != null && !type.isInstance(obj)) {
2683             throw new ClassCastException("Attempt to insert element of type " + obj.getClass() +
2684                     " into collection of type " + type);
2685         }
2686         return obj;
2687     }
2688 
2689     /**
2690      * Returns a set backed by {@code map}.
2691      *
2692      * @throws IllegalArgumentException if the map is not empty
2693      * @since 1.6
2694      */
2695     public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
2696         if (map.isEmpty()) {
2697             return new SetFromMap<E>(map);
2698         }
2699         throw new IllegalArgumentException();
2700     }
2701 
2702     /**
2703      * Returns a last-in, first-out queue as a view of {@code deque}.
2704      *
2705      * @since 1.6
2706      */
2707     public static <T> Queue<T> asLifoQueue(Deque<T> deque) {
2708         return new AsLIFOQueue<T>(deque);
2709     }
2710 
2711     private static class SetFromMap<E> extends AbstractSet<E> implements
2712             Serializable {
2713         private static final long serialVersionUID = 2454657854757543876L;
2714 
2715         // must named as it, to pass serialization compatibility test.
2716         private Map<E, Boolean> m;
2717 
2718         private transient Set<E> backingSet;
2719 
2720         SetFromMap(final Map<E, Boolean> map) {
2721             super();
2722             m = map;
2723             backingSet = map.keySet();
2724         }
2725 
2726         @Override
2727         public boolean equals(Object object) {
2728             return backingSet.equals(object);
2729         }
2730 
2731         @Override
2732         public int hashCode() {
2733             return backingSet.hashCode();
2734         }
2735 
2736         @Override
2737         public boolean add(E object) {
2738             return m.put(object, Boolean.TRUE) == null;
2739         }
2740 
2741         @Override
2742         public void clear() {
2743             m.clear();
2744         }
2745 
2746         @Override
2747         public String toString() {
2748             return backingSet.toString();
2749         }
2750 
2751         @Override
2752         public boolean contains(Object object) {
2753             return backingSet.contains(object);
2754         }
2755 
2756         @Override
2757         public boolean containsAll(Collection<?> collection) {
2758             return backingSet.containsAll(collection);
2759         }
2760 
2761         @Override
2762         public boolean isEmpty() {
2763             return m.isEmpty();
2764         }
2765 
2766         @Override
2767         public boolean remove(Object object) {
2768             return m.remove(object) != null;
2769         }
2770 
2771         @Override
2772         public boolean retainAll(Collection<?> collection) {
2773             return backingSet.retainAll(collection);
2774         }
2775 
2776         @Override
2777         public Object[] toArray() {
2778             return backingSet.toArray();
2779         }
2780 
2781         @Override
2782         public <T> T[] toArray(T[] contents) {
2783             return backingSet.toArray(contents);
2784         }
2785 
2786         @Override
2787         public Iterator<E> iterator() {
2788             return backingSet.iterator();
2789         }
2790 
2791         @Override
2792         public int size() {
2793             return m.size();
2794         }
2795 
2796         @SuppressWarnings("unchecked")
2797         private void readObject(ObjectInputStream stream)
2798                 throws IOException, ClassNotFoundException {
2799             stream.defaultReadObject();
2800             backingSet = m.keySet();
2801         }
2802     }
2803 
2804     private static class AsLIFOQueue<E> extends AbstractQueue<E> implements
2805             Serializable {
2806         private static final long serialVersionUID = 1802017725587941708L;
2807 
2808         // must named as it, to pass serialization compatibility test.
2809         private final Deque<E> q;
2810 
2811         AsLIFOQueue(final Deque<E> deque) {
2812             super();
2813             this.q = deque;
2814         }
2815 
2816         @Override
2817         public Iterator<E> iterator() {
2818             return q.iterator();
2819         }
2820 
2821         @Override
2822         public int size() {
2823             return q.size();
2824         }
2825 
2826         public boolean offer(E o) {
2827             return q.offerFirst(o);
2828         }
2829 
2830         public E peek() {
2831             return q.peekFirst();
2832         }
2833 
2834         public E poll() {
2835             return q.pollFirst();
2836         }
2837 
2838         @Override
2839         public boolean add(E o) {
2840             q.push(o);
2841             return true;
2842         }
2843 
2844         @Override
2845         public void clear() {
2846             q.clear();
2847         }
2848 
2849         @Override
2850         public E element() {
2851             return q.getFirst();
2852         }
2853 
2854         @Override
2855         public E remove() {
2856             return q.pop();
2857         }
2858 
2859         @Override
2860         public boolean contains(Object object) {
2861             return q.contains(object);
2862         }
2863 
2864         @Override
2865         public boolean containsAll(Collection<?> collection) {
2866             return q.containsAll(collection);
2867         }
2868 
2869         @Override
2870         public boolean isEmpty() {
2871             return q.isEmpty();
2872         }
2873 
2874         @Override
2875         public boolean remove(Object object) {
2876             return q.remove(object);
2877         }
2878 
2879         @Override
2880         public boolean removeAll(Collection<?> collection) {
2881             return q.removeAll(collection);
2882         }
2883 
2884         @Override
2885         public boolean retainAll(Collection<?> collection) {
2886             return q.retainAll(collection);
2887         }
2888 
2889         @Override
2890         public Object[] toArray() {
2891             return q.toArray();
2892         }
2893 
2894         @Override
2895         public <T> T[] toArray(T[] contents) {
2896             return q.toArray(contents);
2897         }
2898 
2899         @Override
2900         public String toString() {
2901             return q.toString();
2902         }
2903     }
2904 
2905     /**
2906      * Class represents a dynamically typesafe view of the specified collection.
2907      */
2908     private static class CheckedCollection<E> implements Collection<E>,
2909             Serializable {
2910 
2911         private static final long serialVersionUID = 1578914078182001775L;
2912 
2913         Collection<E> c;
2914 
2915         Class<E> type;
2916 
2917         /**
2918          * Constructs a dynamically typesafe view of the specified collection.
2919          *
2920          * @param c -
2921          *            the collection for which an unmodifiable view is to be
2922          *            constructed.
2923          */
2924         public CheckedCollection(Collection<E> c, Class<E> type) {
2925             if (c == null || type == null) {
2926                 throw new NullPointerException();
2927             }
2928             this.c = c;
2929             this.type = type;
2930         }
2931 
2932         /**
2933          * @see java.util.Collection#size()
2934          */
2935         public int size() {
2936             return c.size();
2937         }
2938 
2939         /**
2940          * @see java.util.Collection#isEmpty()
2941          */
2942         public boolean isEmpty() {
2943             return c.isEmpty();
2944         }
2945 
2946         /**
2947          * @see java.util.Collection#contains(Object)
2948          */
2949         public boolean contains(Object obj) {
2950             return c.contains(obj);
2951         }
2952 
2953         /**
2954          * @see java.util.Collection#iterator()
2955          */
2956         public Iterator<E> iterator() {
2957             Iterator<E> i = c.iterator();
2958             if (i instanceof ListIterator) {
2959                 i = new CheckedListIterator<E>((ListIterator<E>) i, type);
2960             }
2961             return i;
2962         }
2963 
2964         /**
2965          * @see java.util.Collection#toArray()
2966          */
2967         public Object[] toArray() {
2968             return c.toArray();
2969         }
2970 
2971         /**
2972          * @see java.util.Collection#toArray(Object[])
2973          */
2974         public <T> T[] toArray(T[] arr) {
2975             return c.toArray(arr);
2976         }
2977 
2978         /**
2979          * @see java.util.Collection#add(Object)
2980          */
2981         public boolean add(E obj) {
2982             return c.add(checkType(obj, type));
2983         }
2984 
2985         /**
2986          * @see java.util.Collection#remove(Object)
2987          */
2988         public boolean remove(Object obj) {
2989             return c.remove(obj);
2990         }
2991 
2992         /**
2993          * @see java.util.Collection#containsAll(Collection)
2994          */
2995         public boolean containsAll(Collection<?> c1) {
2996             return c.containsAll(c1);
2997         }
2998 
2999         /**
3000          * @see java.util.Collection#addAll(Collection)
3001          */
3002         @SuppressWarnings("unchecked")
3003         public boolean addAll(Collection<? extends E> c1) {
3004             Object[] array = c1.toArray();
3005             for (Object o : array) {
3006                 checkType(o, type);
3007             }
3008             return c.addAll((List<E>) Arrays.asList(array));
3009         }
3010 
3011         /**
3012          * @see java.util.Collection#removeAll(Collection)
3013          */
3014         public boolean removeAll(Collection<?> c1) {
3015             return c.removeAll(c1);
3016         }
3017 
3018         /**
3019          * @see java.util.Collection#retainAll(Collection)
3020          */
3021         public boolean retainAll(Collection<?> c1) {
3022             return c.retainAll(c1);
3023         }
3024 
3025         /**
3026          * @see java.util.Collection#clear()
3027          */
3028         public void clear() {
3029             c.clear();
3030         }
3031 
3032         /**
3033          * @see java.lang.Object#toString()
3034          */
3035         @Override
3036         public String toString() {
3037             return c.toString();
3038         }
3039     }
3040 
3041     /**
3042      * Class represents a dynamically typesafe view of the specified
3043      * ListIterator.
3044      */
3045     private static class CheckedListIterator<E> implements ListIterator<E> {
3046 
3047         private ListIterator<E> i;
3048 
3049         private Class<E> type;
3050 
3051         /**
3052          * Constructs a dynamically typesafe view of the specified ListIterator.
3053          *
3054          * @param i -
3055          *            the listIterator for which a dynamically typesafe view to
3056          *            be constructed.
3057          */
3058         public CheckedListIterator(ListIterator<E> i, Class<E> type) {
3059             this.i = i;
3060             this.type = type;
3061         }
3062 
3063         /**
3064          * @see java.util.Iterator#hasNext()
3065          */
3066         public boolean hasNext() {
3067             return i.hasNext();
3068         }
3069 
3070         /**
3071          * @see java.util.Iterator#next()
3072          */
3073         public E next() {
3074             return i.next();
3075         }
3076 
3077         /**
3078          * @see java.util.Iterator#remove()
3079          */
3080         public void remove() {
3081             i.remove();
3082         }
3083 
3084         /**
3085          * @see java.util.ListIterator#hasPrevious()
3086          */
3087         public boolean hasPrevious() {
3088             return i.hasPrevious();
3089         }
3090 
3091         /**
3092          * @see java.util.ListIterator#previous()
3093          */
3094         public E previous() {
3095             return i.previous();
3096         }
3097 
3098         /**
3099          * @see java.util.ListIterator#nextIndex()
3100          */
3101         public int nextIndex() {
3102             return i.nextIndex();
3103         }
3104 
3105         /**
3106          * @see java.util.ListIterator#previousIndex()
3107          */
3108         public int previousIndex() {
3109             return i.previousIndex();
3110         }
3111 
3112         /**
3113          * @see java.util.ListIterator#set(Object)
3114          */
3115         public void set(E obj) {
3116             i.set(checkType(obj, type));
3117         }
3118 
3119         /**
3120          * @see java.util.ListIterator#add(Object)
3121          */
3122         public void add(E obj) {
3123             i.add(checkType(obj, type));
3124         }
3125     }
3126 
3127     /**
3128      * Class represents a dynamically typesafe view of the specified list.
3129      */
3130     private static class CheckedList<E> extends CheckedCollection<E> implements
3131             List<E> {
3132 
3133         private static final long serialVersionUID = 65247728283967356L;
3134 
3135         List<E> l;
3136 
3137         /**
3138          * Constructs a dynamically typesafe view of the specified list.
3139          *
3140          * @param l -
3141          *            the list for which a dynamically typesafe view is to be
3142          *            constructed.
3143          */
3144         public CheckedList(List<E> l, Class<E> type) {
3145             super(l, type);
3146             this.l = l;
3147         }
3148 
3149         /**
3150          * @see java.util.List#addAll(int, Collection)
3151          */
3152         @SuppressWarnings("unchecked")
3153         public boolean addAll(int index, Collection<? extends E> c1) {
3154             Object[] array = c1.toArray();
3155             for (Object o : array) {
3156                 checkType(o, type);
3157             }
3158             return l.addAll(index, (List<E>) Arrays.asList(array));
3159         }
3160 
3161         /**
3162          * @see java.util.List#get(int)
3163          */
3164         public E get(int index) {
3165             return l.get(index);
3166         }
3167 
3168         /**
3169          * @see java.util.List#set(int, Object)
3170          */
3171         public E set(int index, E obj) {
3172             return l.set(index, checkType(obj, type));
3173         }
3174 
3175         /**
3176          * @see java.util.List#add(int, Object)
3177          */
3178         public void add(int index, E obj) {
3179             l.add(index, checkType(obj, type));
3180         }
3181 
3182         /**
3183          * @see java.util.List#remove(int)
3184          */
3185         public E remove(int index) {
3186             return l.remove(index);
3187         }
3188 
3189         /**
3190          * @see java.util.List#indexOf(Object)
3191          */
3192         public int indexOf(Object obj) {
3193             return l.indexOf(obj);
3194         }
3195 
3196         /**
3197          * @see java.util.List#lastIndexOf(Object)
3198          */
3199         public int lastIndexOf(Object obj) {
3200             return l.lastIndexOf(obj);
3201         }
3202 
3203         /**
3204          * @see java.util.List#listIterator()
3205          */
3206         public ListIterator<E> listIterator() {
3207             return new CheckedListIterator<E>(l.listIterator(), type);
3208         }
3209 
3210         /**
3211          * @see java.util.List#listIterator(int)
3212          */
3213         public ListIterator<E> listIterator(int index) {
3214             return new CheckedListIterator<E>(l.listIterator(index), type);
3215         }
3216 
3217         /**
3218          * @see java.util.List#subList(int, int)
3219          */
3220         public List<E> subList(int fromIndex, int toIndex) {
3221             return checkedList(l.subList(fromIndex, toIndex), type);
3222         }
3223 
3224         /**
3225          * @see java.util.List#equals(Object)
3226          */
3227         @Override
3228         public boolean equals(Object obj) {
3229             return l.equals(obj);
3230         }
3231 
3232         /**
3233          * @see java.util.List#hashCode()
3234          */
3235         @Override
3236         public int hashCode() {
3237             return l.hashCode();
3238         }
3239     }
3240 
3241     /**
3242      * Class represents a dynamically typesafe view of the specified
3243      * randomAccessList.
3244      */
3245     private static class CheckedRandomAccessList<E> extends CheckedList<E>
3246             implements RandomAccess {
3247 
3248         private static final long serialVersionUID = 1638200125423088369L;
3249 
3250         /**
3251          * Constructs a dynamically typesafe view of the specified
3252          * randomAccessList.
3253          *
3254          * @param l -
3255          *            the randomAccessList for which a dynamically typesafe view
3256          *            is to be constructed.
3257          */
3258         public CheckedRandomAccessList(List<E> l, Class<E> type) {
3259             super(l, type);
3260         }
3261     }
3262 
3263     /**
3264      * Class represents a dynamically typesafe view of the specified set.
3265      */
3266     private static class CheckedSet<E> extends CheckedCollection<E> implements
3267             Set<E> {
3268 
3269         private static final long serialVersionUID = 4694047833775013803L;
3270 
3271         /**
3272          * Constructs a dynamically typesafe view of the specified set.
3273          *
3274          * @param s -
3275          *            the set for which a dynamically typesafe view is to be
3276          *            constructed.
3277          */
3278         public CheckedSet(Set<E> s, Class<E> type) {
3279             super(s, type);
3280         }
3281 
3282         /**
3283          * @see java.util.Set#equals(Object)
3284          */
3285         @Override
3286         public boolean equals(Object obj) {
3287             return c.equals(obj);
3288         }
3289 
3290         /**
3291          * @see java.util.Set#hashCode()
3292          */
3293         @Override
3294         public int hashCode() {
3295             return c.hashCode();
3296         }
3297 
3298     }
3299 
3300     /**
3301      * Class represents a dynamically typesafe view of the specified map.
3302      */
3303     private static class CheckedMap<K, V> implements Map<K, V>, Serializable {
3304 
3305         private static final long serialVersionUID = 5742860141034234728L;
3306 
3307         Map<K, V> m;
3308 
3309         Class<K> keyType;
3310 
3311         Class<V> valueType;
3312 
3313         /**
3314          * Constructs a dynamically typesafe view of the specified map.
3315          *
3316          * @param m -
3317          *            the map for which a dynamically typesafe view is to be
3318          *            constructed.
3319          */
3320         private CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {
3321             if (m == null || keyType == null || valueType == null) {
3322                 throw new NullPointerException();
3323             }
3324             this.m = m;
3325             this.keyType = keyType;
3326             this.valueType = valueType;
3327         }
3328 
3329         /**
3330          * @see java.util.Map#size()
3331          */
3332         public int size() {
3333             return m.size();
3334         }
3335 
3336         /**
3337          * @see java.util.Map#isEmpty()
3338          */
3339         public boolean isEmpty() {
3340             return m.isEmpty();
3341         }
3342 
3343         /**
3344          * @see java.util.Map#containsKey(Object)
3345          */
3346         public boolean containsKey(Object key) {
3347             return m.containsKey(key);
3348         }
3349 
3350         /**
3351          * @see java.util.Map#containsValue(Object)
3352          */
3353         public boolean containsValue(Object value) {
3354             return m.containsValue(value);
3355         }
3356 
3357         /**
3358          * @see java.util.Map#get(Object)
3359          */
3360         public V get(Object key) {
3361             return m.get(key);
3362         }
3363 
3364         /**
3365          * @see java.util.Map#put(Object, Object)
3366          */
3367         public V put(K key, V value) {
3368             return m.put(checkType(key, keyType), checkType(value, valueType));
3369         }
3370 
3371         /**
3372          * @see java.util.Map#remove(Object)
3373          */
3374         public V remove(Object key) {
3375             return m.remove(key);
3376         }
3377 
3378         /**
3379          * @see java.util.Map#putAll(Map)
3380          */
3381         @SuppressWarnings("unchecked")
3382         public void putAll(Map<? extends K, ? extends V> map) {
3383             int size = map.size();
3384             if (size == 0) {
3385                 return;
3386             }
3387             Map.Entry<? extends K, ? extends V>[] entries = new Map.Entry[size];
3388             Iterator<? extends Map.Entry<? extends K, ? extends V>> it = map
3389                     .entrySet().iterator();
3390             for (int i = 0; i < size; i++) {
3391                 Map.Entry<? extends K, ? extends V> e = it.next();
3392                 checkType(e.getKey(), keyType);
3393                 checkType(e.getValue(), valueType);
3394                 entries[i] = e;
3395             }
3396             for (int i = 0; i < size; i++) {
3397                 m.put(entries[i].getKey(), entries[i].getValue());
3398             }
3399         }
3400 
3401         /**
3402          * @see java.util.Map#clear()
3403          */
3404         public void clear() {
3405             m.clear();
3406         }
3407 
3408         /**
3409          * @see java.util.Map#keySet()
3410          */
3411         public Set<K> keySet() {
3412             return m.keySet();
3413         }
3414 
3415         /**
3416          * @see java.util.Map#values()
3417          */
3418         public Collection<V> values() {
3419             return m.values();
3420         }
3421 
3422         /**
3423          * @see java.util.Map#entrySet()
3424          */
3425         public Set<Map.Entry<K, V>> entrySet() {
3426             return new CheckedEntrySet<K, V>(m.entrySet(), valueType);
3427         }
3428 
3429         /**
3430          * @see java.util.Map#equals(Object)
3431          */
3432         @Override
3433         public boolean equals(Object obj) {
3434             return m.equals(obj);
3435         }
3436 
3437         /**
3438          * @see java.util.Map#hashCode()
3439          */
3440         @Override
3441         public int hashCode() {
3442             return m.hashCode();
3443         }
3444 
3445         /**
3446          * @see java.lang.Object#toString()
3447          */
3448         @Override
3449         public String toString() {
3450             return m.toString();
3451         }
3452 
3453         /**
3454          * Class represents a dynamically typesafe view of the specified map
3455          * entry.
3456          */
3457         private static class CheckedEntry<K, V> implements Map.Entry<K, V> {
3458 
3459             Map.Entry<K, V> e;
3460 
3461             Class<V> valueType;
3462 
3463             /**
3464              * Constructs a dynamically typesafe view of the specified map
3465              * entry.
3466              *
3467              * @param e
3468              *            the map entry for which a dynamically typesafe view is
3469              *            to be constructed.
3470              * @param valueType
3471              *            the type of the value
3472              */
3473             public CheckedEntry(Map.Entry<K, V> e, Class<V> valueType) {
3474                 if (e == null) {
3475                     throw new NullPointerException();
3476                 }
3477                 this.e = e;
3478                 this.valueType = valueType;
3479             }
3480 
3481             /**
3482              * @see java.util.Map.Entry#getKey()
3483              */
3484             public K getKey() {
3485                 return e.getKey();
3486             }
3487 
3488             /**
3489              * @see java.util.Map.Entry#getValue()
3490              */
3491             public V getValue() {
3492                 return e.getValue();
3493             }
3494 
3495             /**
3496              * @see java.util.Map.Entry#setValue(Object)
3497              */
3498             public V setValue(V obj) {
3499                 return e.setValue(checkType(obj, valueType));
3500             }
3501 
3502             /**
3503              * @see java.util.Map.Entry#equals(Object)
3504              */
3505             @Override
3506             public boolean equals(Object obj) {
3507                 return e.equals(obj);
3508             }
3509 
3510             /**
3511              * @see java.util.Map.Entry#hashCode()
3512              */
3513             @Override
3514             public int hashCode() {
3515                 return e.hashCode();
3516             }
3517         }
3518 
3519         /**
3520          * Class represents a dynamically typesafe view of the specified entry
3521          * set.
3522          */
3523         private static class CheckedEntrySet<K, V> implements
3524                 Set<Map.Entry<K, V>> {
3525 
3526             Set<Map.Entry<K, V>> s;
3527 
3528             Class<V> valueType;
3529 
3530             /**
3531              * Constructs a dynamically typesafe view of the specified entry
3532              * set.
3533              *
3534              * @param s -
3535              *            the entry set for which a dynamically typesafe view is
3536              *            to be constructed.
3537              */
3538             public CheckedEntrySet(Set<Map.Entry<K, V>> s, Class<V> valueType) {
3539                 this.s = s;
3540                 this.valueType = valueType;
3541             }
3542 
3543             /**
3544              * @see java.util.Set#iterator()
3545              */
3546             public Iterator<Map.Entry<K, V>> iterator() {
3547                 return new CheckedEntryIterator<K, V>(s.iterator(), valueType);
3548             }
3549 
3550             /**
3551              * @see java.util.Set#toArray()
3552              */
3553             public Object[] toArray() {
3554                 int thisSize = size();
3555                 Object[] array = new Object[thisSize];
3556                 Iterator<?> it = iterator();
3557                 for (int i = 0; i < thisSize; i++) {
3558                     array[i] = it.next();
3559                 }
3560                 return array;
3561             }
3562 
3563             /**
3564              * @see java.util.Set#toArray(Object[])
3565              */
3566             @SuppressWarnings("unchecked")
3567             public <T> T[] toArray(T[] array) {
3568                 int thisSize = size();
3569                 if (array.length < thisSize) {
3570                     Class<?> ct = array.getClass().getComponentType();
3571                     array = (T[]) Array.newInstance(ct, thisSize);
3572                 }
3573                 Iterator<?> it = iterator();
3574                 for (int i = 0; i < thisSize; i++) {
3575                     array[i] = (T) it.next();
3576                 }
3577                 if (thisSize < array.length) {
3578                     array[thisSize] = null;
3579                 }
3580                 return array;
3581             }
3582 
3583             /**
3584              * @see java.util.Set#retainAll(Collection)
3585              */
3586             public boolean retainAll(Collection<?> c) {
3587                 return s.retainAll(c);
3588             }
3589 
3590             /**
3591              * @see java.util.Set#removeAll(Collection)
3592              */
3593             public boolean removeAll(Collection<?> c) {
3594                 return s.removeAll(c);
3595             }
3596 
3597             /**
3598              * @see java.util.Set#containsAll(Collection)
3599              */
3600             public boolean containsAll(Collection<?> c) {
3601                 return s.containsAll(c);
3602             }
3603 
3604             /**
3605              * @see java.util.Set#addAll(Collection)
3606              */
3607             public boolean addAll(Collection<? extends Map.Entry<K, V>> c) {
3608                 throw new UnsupportedOperationException();
3609             }
3610 
3611             /**
3612              * @see java.util.Set#remove(Object)
3613              */
3614             public boolean remove(Object o) {
3615                 return s.remove(o);
3616             }
3617 
3618             /**
3619              * @see java.util.Set#contains(Object)
3620              */
3621             public boolean contains(Object o) {
3622                 return s.contains(o);
3623             }
3624 
3625             /**
3626              * @see java.util.Set#add(Object)
3627              */
3628             public boolean add(Map.Entry<K, V> o) {
3629                 throw new UnsupportedOperationException();
3630             }
3631 
3632             /**
3633              * @see java.util.Set#isEmpty()
3634              */
3635             public boolean isEmpty() {
3636                 return s.isEmpty();
3637             }
3638 
3639             /**
3640              * @see java.util.Set#clear()
3641              */
3642             public void clear() {
3643                 s.clear();
3644             }
3645 
3646             /**
3647              * @see java.util.Set#size()
3648              */
3649             public int size() {
3650                 return s.size();
3651             }
3652 
3653             /**
3654              * @see java.util.Set#hashCode()
3655              */
3656             @Override
3657             public int hashCode() {
3658                 return s.hashCode();
3659             }
3660 
3661             /**
3662              * @see java.util.Set#equals(Object)
3663              */
3664             @Override
3665             public boolean equals(Object object) {
3666                 return s.equals(object);
3667             }
3668 
3669             /**
3670              * Class represents a dynamically typesafe view of the specified
3671              * entry iterator.
3672              */
3673             private static class CheckedEntryIterator<K, V> implements
3674                     Iterator<Map.Entry<K, V>> {
3675 
3676                 Iterator<Map.Entry<K, V>> i;
3677 
3678                 Class<V> valueType;
3679 
3680                 /**
3681                  * Constructs a dynamically typesafe view of the specified entry
3682                  * iterator.
3683                  *
3684                  * @param i -
3685                  *            the entry iterator for which a dynamically
3686                  *            typesafe view is to be constructed.
3687                  */
3688                 public CheckedEntryIterator(Iterator<Map.Entry<K, V>> i,
3689                         Class<V> valueType) {
3690                     this.i = i;
3691                     this.valueType = valueType;
3692                 }
3693 
3694                 /**
3695                  * @see java.util.Iterator#hasNext()
3696                  */
3697                 public boolean hasNext() {
3698                     return i.hasNext();
3699                 }
3700 
3701                 /**
3702                  * @see java.util.Iterator#remove()
3703                  */
3704                 public void remove() {
3705                     i.remove();
3706                 }
3707 
3708                 /**
3709                  * @see java.util.Iterator#next()
3710                  */
3711                 public Map.Entry<K, V> next() {
3712                     return new CheckedEntry<K, V>(i.next(), valueType);
3713                 }
3714             }
3715 
3716         }
3717 
3718     }
3719 
3720     /**
3721      * Class represents a dynamically typesafe view of the specified sortedSet.
3722      */
3723     private static class CheckedSortedSet<E> extends CheckedSet<E> implements
3724             SortedSet<E> {
3725 
3726         private static final long serialVersionUID = 1599911165492914959L;
3727 
3728         private SortedSet<E> ss;
3729 
3730         /**
3731          * Constructs a dynamically typesafe view of the specified sortedSet.
3732          *
3733          * @param s -
3734          *            the sortedSet for which a dynamically typesafe view is to
3735          *            be constructed.
3736          */
3737         public CheckedSortedSet(SortedSet<E> s, Class<E> type) {
3738             super(s, type);
3739             this.ss = s;
3740         }
3741 
3742         /**
3743          * @see java.util.SortedSet#comparator()
3744          */
3745         public Comparator<? super E> comparator() {
3746             return ss.comparator();
3747         }
3748 
3749         /**
3750          * @see java.util.SortedSet#subSet(Object, Object)
3751          */
3752         public SortedSet<E> subSet(E fromElement, E toElement) {
3753             return new CheckedSortedSet<E>(ss.subSet(fromElement, toElement),
3754                     type);
3755         }
3756 
3757         /**
3758          * @see java.util.SortedSet#headSet(Object)
3759          */
3760         public SortedSet<E> headSet(E toElement) {
3761             return new CheckedSortedSet<E>(ss.headSet(toElement), type);
3762         }
3763 
3764         /**
3765          * @see java.util.SortedSet#tailSet(Object)
3766          */
3767         public SortedSet<E> tailSet(E fromElement) {
3768             return new CheckedSortedSet<E>(ss.tailSet(fromElement), type);
3769         }
3770 
3771         /**
3772          * @see java.util.SortedSet#first()
3773          */
3774         public E first() {
3775             return ss.first();
3776         }
3777 
3778         /**
3779          * @see java.util.SortedSet#last()
3780          */
3781         public E last() {
3782             return ss.last();
3783         }
3784     }
3785 
3786     /**
3787      * Class represents a dynamically typesafe view of the specified sortedMap.
3788      */
3789     private static class CheckedSortedMap<K, V> extends CheckedMap<K, V>
3790             implements SortedMap<K, V> {
3791 
3792         private static final long serialVersionUID = 1599671320688067438L;
3793 
3794         SortedMap<K, V> sm;
3795 
3796         /**
3797          * Constructs a dynamically typesafe view of the specified sortedMap.
3798          *
3799          * @param m -
3800          *            the sortedMap for which a dynamically typesafe view is to
3801          *            be constructed.
3802          */
3803         CheckedSortedMap(SortedMap<K, V> m, Class<K> keyType, Class<V> valueType) {
3804             super(m, keyType, valueType);
3805             this.sm = m;
3806         }
3807 
3808         /**
3809          * @see java.util.SortedMap#comparator()
3810          */
3811         public Comparator<? super K> comparator() {
3812             return sm.comparator();
3813         }
3814 
3815         /**
3816          * @see java.util.SortedMap#subMap(Object, Object)
3817          */
3818         public SortedMap<K, V> subMap(K fromKey, K toKey) {
3819             return new CheckedSortedMap<K, V>(sm.subMap(fromKey, toKey),
3820                     keyType, valueType);
3821         }
3822 
3823         /**
3824          * @see java.util.SortedMap#headMap(Object)
3825          */
3826         public SortedMap<K, V> headMap(K toKey) {
3827             return new CheckedSortedMap<K, V>(sm.headMap(toKey), keyType,
3828                     valueType);
3829         }
3830 
3831         /**
3832          * @see java.util.SortedMap#tailMap(Object)
3833          */
3834         public SortedMap<K, V> tailMap(K fromKey) {
3835             return new CheckedSortedMap<K, V>(sm.tailMap(fromKey), keyType,
3836                     valueType);
3837         }
3838 
3839         /**
3840          * @see java.util.SortedMap#firstKey()
3841          */
3842         public K firstKey() {
3843             return sm.firstKey();
3844         }
3845 
3846         /**
3847          * @see java.util.SortedMap#lastKey()
3848          */
3849         public K lastKey() {
3850             return sm.lastKey();
3851         }
3852     }
3853 }
3854