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