001 /* 002 * Copyright (C) 2007 Google Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package com.google.common.collect; 018 019 import static com.google.common.base.Preconditions.checkNotNull; 020 021 import com.google.common.annotations.GwtCompatible; 022 023 import java.io.InvalidObjectException; 024 import java.io.ObjectInputStream; 025 import java.io.Serializable; 026 import java.util.ArrayList; 027 import java.util.Collection; 028 import java.util.Collections; 029 import java.util.Iterator; 030 import java.util.List; 031 import java.util.RandomAccess; 032 033 import javax.annotation.Nullable; 034 035 /** 036 * A high-performance, immutable, random-access {@code List} implementation. 037 * Does not permit null elements. 038 * 039 * <p>Unlike {@link Collections#unmodifiableList}, which is a <i>view</i> of a 040 * separate collection that can still change, an instance of {@code 041 * ImmutableList} contains its own private data and will <i>never</i> change. 042 * {@code ImmutableList} is convenient for {@code public static final} lists 043 * ("constant lists") and also lets you easily make a "defensive copy" of a list 044 * provided to your class by a caller. 045 * 046 * <p><b>Note</b>: Although this class is not final, it cannot be subclassed as 047 * it has no public or protected constructors. Thus, instances of this type are 048 * guaranteed to be immutable. 049 * 050 * @see ImmutableMap 051 * @see ImmutableSet 052 * @author Kevin Bourrillion 053 * @since 2 (imported from Google Collections Library) 054 */ 055 @GwtCompatible(serializable = true, emulated = true) 056 @SuppressWarnings("serial") // we're overriding default serialization 057 public abstract class ImmutableList<E> extends ImmutableCollection<E> 058 implements List<E>, RandomAccess { 059 /** 060 * Returns the empty immutable list. This set behaves and performs comparably 061 * to {@link Collections#emptyList}, and is preferable mainly for consistency 062 * and maintainability of your code. 063 */ 064 // Casting to any type is safe because the list will never hold any elements. 065 @SuppressWarnings("unchecked") 066 public static <E> ImmutableList<E> of() { 067 return (ImmutableList<E>) EmptyImmutableList.INSTANCE; 068 } 069 070 /** 071 * Returns an immutable list containing a single element. This list behaves 072 * and performs comparably to {@link Collections#singleton}, but will not 073 * accept a null element. It is preferable mainly for consistency and 074 * maintainability of your code. 075 * 076 * @throws NullPointerException if {@code element} is null 077 */ 078 public static <E> ImmutableList<E> of(E element) { 079 return new SingletonImmutableList<E>(element); 080 } 081 082 /** 083 * Returns an immutable list containing the given elements, in order. 084 * 085 * @throws NullPointerException if any element is null 086 */ 087 public static <E> ImmutableList<E> of(E e1, E e2) { 088 return new RegularImmutableList<E>(copyIntoArray(e1, e2)); 089 } 090 091 /** 092 * Returns an immutable list containing the given elements, in order. 093 * 094 * @throws NullPointerException if any element is null 095 */ 096 public static <E> ImmutableList<E> of(E e1, E e2, E e3) { 097 return new RegularImmutableList<E>(copyIntoArray(e1, e2, e3)); 098 } 099 100 /** 101 * Returns an immutable list containing the given elements, in order. 102 * 103 * @throws NullPointerException if any element is null 104 */ 105 public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4) { 106 return new RegularImmutableList<E>(copyIntoArray(e1, e2, e3, e4)); 107 } 108 109 /** 110 * Returns an immutable list containing the given elements, in order. 111 * 112 * @throws NullPointerException if any element is null 113 */ 114 public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5) { 115 return new RegularImmutableList<E>(copyIntoArray(e1, e2, e3, e4, e5)); 116 } 117 118 /** 119 * Returns an immutable list containing the given elements, in order. 120 * 121 * @throws NullPointerException if any element is null 122 */ 123 public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) { 124 return new RegularImmutableList<E>(copyIntoArray(e1, e2, e3, e4, e5, e6)); 125 } 126 127 /** 128 * Returns an immutable list containing the given elements, in order. 129 * 130 * @throws NullPointerException if any element is null 131 */ 132 public static <E> ImmutableList<E> of( 133 E e1, E e2, E e3, E e4, E e5, E e6, E e7) { 134 return new RegularImmutableList<E>( 135 copyIntoArray(e1, e2, e3, e4, e5, e6, e7)); 136 } 137 138 /** 139 * Returns an immutable list containing the given elements, in order. 140 * 141 * @throws NullPointerException if any element is null 142 */ 143 public static <E> ImmutableList<E> of( 144 E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { 145 return new RegularImmutableList<E>( 146 copyIntoArray(e1, e2, e3, e4, e5, e6, e7, e8)); 147 } 148 149 /** 150 * Returns an immutable list containing the given elements, in order. 151 * 152 * @throws NullPointerException if any element is null 153 */ 154 public static <E> ImmutableList<E> of( 155 E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { 156 return new RegularImmutableList<E>( 157 copyIntoArray(e1, e2, e3, e4, e5, e6, e7, e8, e9)); 158 } 159 160 /** 161 * Returns an immutable list containing the given elements, in order. 162 * 163 * @throws NullPointerException if any element is null 164 */ 165 public static <E> ImmutableList<E> of( 166 E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { 167 return new RegularImmutableList<E>( 168 copyIntoArray(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10)); 169 } 170 171 /** 172 * Returns an immutable list containing the given elements, in order. 173 * 174 * @throws NullPointerException if any element is null 175 */ 176 public static <E> ImmutableList<E> of( 177 E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) { 178 return new RegularImmutableList<E>( 179 copyIntoArray(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11)); 180 } 181 182 // These go up to eleven. After that, you just get the varargs form, and 183 // whatever warnings might come along with it. :( 184 185 /** 186 * Returns an immutable list containing the given elements, in order. 187 * 188 * @throws NullPointerException if any element is null 189 * @since 3 (source-compatible since release 2) 190 */ 191 public static <E> ImmutableList<E> of( 192 E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, 193 E... others) { 194 final int paramCount = 12; 195 Object[] array = new Object[paramCount + others.length]; 196 copyIntoArray(array, 0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12); 197 copyIntoArray(array, paramCount, others); 198 return new RegularImmutableList<E>(array); 199 } 200 201 /** 202 * Returns an immutable list containing the given elements, in order. 203 * 204 * @deprecated use {@link #copyOf(Object[])} 205 * @throws NullPointerException if any of {@code elements} is null 206 * @since 2 (changed from varargs in release 3) 207 */ 208 @Deprecated 209 public static <E> ImmutableList<E> of(E[] elements) { 210 switch (elements.length) { 211 case 0: 212 return ImmutableList.of(); 213 case 1: 214 return new SingletonImmutableList<E>(elements[0]); 215 default: 216 return new RegularImmutableList<E>(copyIntoArray(elements)); 217 } 218 } 219 220 /** 221 * Returns an immutable list containing the given elements, in order. If 222 * {@code elements} is a {@link Collection}, this method behaves exactly as 223 * {@link #copyOf(Collection)}; otherwise, it behaves exactly as {@code 224 * copyOf(elements.iterator()}. 225 * 226 * @throws NullPointerException if any of {@code elements} is null 227 */ 228 @SuppressWarnings("unchecked") // bugs.sun.com/view_bug.do?bug_id=6558557 229 public static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements) { 230 checkNotNull(elements); 231 return (elements instanceof Collection) 232 ? copyOf((Collection<? extends E>) elements) 233 : copyOf(elements.iterator()); 234 } 235 236 /** 237 * Returns an immutable list containing the given elements, in order. 238 * 239 * <p><b>Note:</b> Despite what the method name suggests, if {@code elements} 240 * is an {@code ImmutableList}, no copy will actually be performed, and the 241 * given list itself will be returned. 242 * 243 * <p>Note that if {@code list} is a {@code List<String>}, then {@code 244 * ImmutableList.copyOf(list)} returns an {@code ImmutableList<String>} 245 * containing each of the strings in {@code list}, while 246 * ImmutableList.of(list)} returns an {@code ImmutableList<List<String>>} 247 * containing one element (the given list itself). 248 * 249 * <p>This method is safe to use even when {@code elements} is a synchronized 250 * or concurrent collection that is currently being modified by another 251 * thread. 252 * 253 * @throws NullPointerException if any of {@code elements} is null 254 * @since 2 (Iterable overload existed previously) 255 */ 256 public static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) { 257 if (elements instanceof ImmutableCollection) { 258 /* 259 * TODO: When given an ImmutableList that's a sublist, copy the referenced 260 * portion of the array into a new array to save space? 261 */ 262 @SuppressWarnings("unchecked") // all supported methods are covariant 263 ImmutableCollection<E> list = (ImmutableCollection<E>) elements; 264 return list.asList(); 265 } 266 return copyFromCollection(elements); 267 } 268 269 /** 270 * Returns an immutable list containing the given elements, in order. 271 * 272 * @throws NullPointerException if any of {@code elements} is null 273 */ 274 public static <E> ImmutableList<E> copyOf(Iterator<? extends E> elements) { 275 return copyFromCollection(Lists.newArrayList(elements)); 276 } 277 278 /** 279 * Returns an immutable list containing the given elements, in order. 280 * 281 * @throws NullPointerException if any of {@code elements} is null 282 * @since 3 283 */ 284 public static <E> ImmutableList<E> copyOf(E[] elements) { 285 switch (elements.length) { 286 case 0: 287 return ImmutableList.of(); 288 case 1: 289 return new SingletonImmutableList<E>(elements[0]); 290 default: 291 return new RegularImmutableList<E>(copyIntoArray(elements)); 292 } 293 } 294 295 private static <E> ImmutableList<E> copyFromCollection( 296 Collection<? extends E> collection) { 297 Object[] elements = collection.toArray(); 298 switch (elements.length) { 299 case 0: 300 return of(); 301 case 1: 302 @SuppressWarnings("unchecked") // collection had only Es in it 303 ImmutableList<E> list = new SingletonImmutableList<E>((E) elements[0]); 304 return list; 305 default: 306 return new RegularImmutableList<E>(copyIntoArray(elements)); 307 } 308 } 309 310 ImmutableList() {} 311 312 // This declaration is needed to make List.iterator() and 313 // ImmutableCollection.iterator() consistent. 314 @Override public abstract UnmodifiableIterator<E> iterator(); 315 316 // Mark these two methods with @Nullable 317 318 public abstract int indexOf(@Nullable Object object); 319 320 public abstract int lastIndexOf(@Nullable Object object); 321 322 // constrain the return type to ImmutableList<E> 323 324 /** 325 * Returns an immutable list of the elements between the specified {@code 326 * fromIndex}, inclusive, and {@code toIndex}, exclusive. (If {@code 327 * fromIndex} and {@code toIndex} are equal, the empty immutable list is 328 * returned.) 329 */ 330 public abstract ImmutableList<E> subList(int fromIndex, int toIndex); 331 332 /** 333 * Guaranteed to throw an exception and leave the list unmodified. 334 * 335 * @throws UnsupportedOperationException always 336 */ 337 public final boolean addAll(int index, Collection<? extends E> newElements) { 338 throw new UnsupportedOperationException(); 339 } 340 341 /** 342 * Guaranteed to throw an exception and leave the list unmodified. 343 * 344 * @throws UnsupportedOperationException always 345 */ 346 public final E set(int index, E element) { 347 throw new UnsupportedOperationException(); 348 } 349 350 /** 351 * Guaranteed to throw an exception and leave the list unmodified. 352 * 353 * @throws UnsupportedOperationException always 354 */ 355 public final void add(int index, E element) { 356 throw new UnsupportedOperationException(); 357 } 358 359 /** 360 * Guaranteed to throw an exception and leave the list unmodified. 361 * 362 * @throws UnsupportedOperationException always 363 */ 364 public final E remove(int index) { 365 throw new UnsupportedOperationException(); 366 } 367 368 private static Object[] copyIntoArray(Object... source) { 369 return copyIntoArray(new Object[source.length], 0, source); 370 } 371 372 private static Object[] copyIntoArray(Object[] dest, int pos, 373 Object... source) { 374 int index = pos; 375 for (Object element : source) { 376 if (element == null) { 377 throw new NullPointerException("at index " + index); 378 } 379 dest[index++] = element; 380 } 381 return dest; 382 } 383 384 /** 385 * Returns this list instance. 386 * 387 * @since 2 388 */ 389 @Override public ImmutableList<E> asList() { 390 return this; 391 } 392 393 /* 394 * Serializes ImmutableLists as their logical contents. This ensures that 395 * implementation types do not leak into the serialized representation. 396 */ 397 private static class SerializedForm implements Serializable { 398 final Object[] elements; 399 SerializedForm(Object[] elements) { 400 this.elements = elements; 401 } 402 Object readResolve() { 403 return copyOf(elements); 404 } 405 private static final long serialVersionUID = 0; 406 } 407 408 private void readObject(ObjectInputStream stream) 409 throws InvalidObjectException { 410 throw new InvalidObjectException("Use SerializedForm"); 411 } 412 413 @Override Object writeReplace() { 414 return new SerializedForm(toArray()); 415 } 416 417 /** 418 * Returns a new builder. The generated builder is equivalent to the builder 419 * created by the {@link Builder} constructor. 420 */ 421 public static <E> Builder<E> builder() { 422 return new Builder<E>(); 423 } 424 425 /** 426 * A builder for creating immutable list instances, especially 427 * {@code public static final} lists ("constant lists"). 428 * 429 * <p>Example: 430 * <pre> {@code 431 * public static final ImmutableList<Color> GOOGLE_COLORS 432 * = new ImmutableList.Builder<Color>() 433 * .addAll(WEBSAFE_COLORS) 434 * .add(new Color(0, 191, 255)) 435 * .build();}</pre> 436 * 437 * <p>Builder instances can be reused - it is safe to call {@link #build} 438 * multiple times to build multiple lists in series. Each new list 439 * contains the one created before it. 440 */ 441 public static final class Builder<E> extends ImmutableCollection.Builder<E> { 442 private final ArrayList<E> contents = Lists.newArrayList(); 443 444 /** 445 * Creates a new builder. The returned builder is equivalent to the builder 446 * generated by {@link ImmutableList#builder}. 447 */ 448 public Builder() {} 449 450 /** 451 * Adds {@code element} to the {@code ImmutableList}. 452 * 453 * @param element the element to add 454 * @return this {@code Builder} object 455 * @throws NullPointerException if {@code element} is null 456 */ 457 @Override public Builder<E> add(E element) { 458 contents.add(checkNotNull(element)); 459 return this; 460 } 461 462 /** 463 * Adds each element of {@code elements} to the {@code ImmutableList}. 464 * 465 * @param elements the {@code Iterable} to add to the {@code ImmutableList} 466 * @return this {@code Builder} object 467 * @throws NullPointerException if {@code elements} is null or contains a 468 * null element 469 */ 470 @Override public Builder<E> addAll(Iterable<? extends E> elements) { 471 if (elements instanceof Collection) { 472 Collection<?> collection = (Collection<?>) elements; 473 contents.ensureCapacity(contents.size() + collection.size()); 474 } 475 super.addAll(elements); 476 return this; 477 } 478 479 /** 480 * Adds each element of {@code elements} to the {@code ImmutableList}. 481 * 482 * @param elements the {@code Iterable} to add to the {@code ImmutableList} 483 * @return this {@code Builder} object 484 * @throws NullPointerException if {@code elements} is null or contains a 485 * null element 486 */ 487 @Override public Builder<E> add(E... elements) { 488 contents.ensureCapacity(contents.size() + elements.length); 489 super.add(elements); 490 return this; 491 } 492 493 /** 494 * Adds each element of {@code elements} to the {@code ImmutableList}. 495 * 496 * @param elements the {@code Iterable} to add to the {@code ImmutableList} 497 * @return this {@code Builder} object 498 * @throws NullPointerException if {@code elements} is null or contains a 499 * null element 500 */ 501 @Override public Builder<E> addAll(Iterator<? extends E> elements) { 502 super.addAll(elements); 503 return this; 504 } 505 506 /** 507 * Returns a newly-created {@code ImmutableList} based on the contents of 508 * the {@code Builder}. 509 */ 510 @Override public ImmutableList<E> build() { 511 return copyOf(contents); 512 } 513 } 514 } 515