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