001/* 002 * Copyright (C) 2007 The Guava Authors 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 017package com.google.common.collect; 018 019import static com.google.common.base.Preconditions.checkArgument; 020import static com.google.common.base.Preconditions.checkElementIndex; 021import static com.google.common.base.Preconditions.checkNotNull; 022import static com.google.common.base.Preconditions.checkPositionIndexes; 023import static com.google.common.collect.CollectPreconditions.checkNonnegative; 024import static com.google.common.collect.ObjectArrays.checkElementsNotNull; 025import static com.google.common.collect.RegularImmutableList.EMPTY; 026 027import com.google.common.annotations.Beta; 028import com.google.common.annotations.GwtCompatible; 029import com.google.common.annotations.VisibleForTesting; 030import com.google.errorprone.annotations.CanIgnoreReturnValue; 031import java.io.InvalidObjectException; 032import java.io.ObjectInputStream; 033import java.io.Serializable; 034import java.util.Arrays; 035import java.util.Collection; 036import java.util.Collections; 037import java.util.Comparator; 038import java.util.Iterator; 039import java.util.List; 040import java.util.RandomAccess; 041import java.util.Spliterator; 042import java.util.function.Consumer; 043import java.util.function.UnaryOperator; 044import java.util.stream.Collector; 045import org.checkerframework.checker.nullness.qual.Nullable; 046 047/** 048 * A {@link List} whose contents will never change, with many other important properties detailed at 049 * {@link ImmutableCollection}. 050 * 051 * <p>See the Guava User Guide article on <a href= 052 * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained"> immutable collections</a>. 053 * 054 * @see ImmutableMap 055 * @see ImmutableSet 056 * @author Kevin Bourrillion 057 * @since 2.0 058 */ 059@GwtCompatible(serializable = true, emulated = true) 060@SuppressWarnings("serial") // we're overriding default serialization 061public abstract class ImmutableList<E> extends ImmutableCollection<E> 062 implements List<E>, RandomAccess { 063 064 /** 065 * Returns a {@code Collector} that accumulates the input elements into a new {@code 066 * ImmutableList}, in encounter order. 067 * 068 * @since 21.0 069 */ 070 @Beta 071 public static <E> Collector<E, ?, ImmutableList<E>> toImmutableList() { 072 return CollectCollectors.toImmutableList(); 073 } 074 075 /** 076 * Returns the empty immutable list. This list behaves and performs comparably to {@link 077 * Collections#emptyList}, and is preferable mainly for consistency and maintainability of your 078 * code. 079 */ 080 // Casting to any type is safe because the list will never hold any elements. 081 @SuppressWarnings("unchecked") 082 public static <E> ImmutableList<E> of() { 083 return (ImmutableList<E>) EMPTY; 084 } 085 086 /** 087 * Returns an immutable list containing a single element. This list behaves and performs 088 * comparably to {@link Collections#singleton}, but will not accept a null element. It is 089 * preferable mainly for consistency and maintainability of your code. 090 * 091 * @throws NullPointerException if {@code element} is null 092 */ 093 public static <E> ImmutableList<E> of(E element) { 094 return new SingletonImmutableList<E>(element); 095 } 096 097 /** 098 * Returns an immutable list containing the given elements, in order. 099 * 100 * @throws NullPointerException if any element is null 101 */ 102 public static <E> ImmutableList<E> of(E e1, E e2) { 103 return construct(e1, e2); 104 } 105 106 /** 107 * Returns an immutable list containing the given elements, in order. 108 * 109 * @throws NullPointerException if any element is null 110 */ 111 public static <E> ImmutableList<E> of(E e1, E e2, E e3) { 112 return construct(e1, e2, e3); 113 } 114 115 /** 116 * Returns an immutable list containing the given elements, in order. 117 * 118 * @throws NullPointerException if any element is null 119 */ 120 public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4) { 121 return construct(e1, e2, e3, e4); 122 } 123 124 /** 125 * Returns an immutable list containing the given elements, in order. 126 * 127 * @throws NullPointerException if any element is null 128 */ 129 public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5) { 130 return construct(e1, e2, e3, e4, e5); 131 } 132 133 /** 134 * Returns an immutable list containing the given elements, in order. 135 * 136 * @throws NullPointerException if any element is null 137 */ 138 public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) { 139 return construct(e1, e2, e3, e4, e5, e6); 140 } 141 142 /** 143 * Returns an immutable list containing the given elements, in order. 144 * 145 * @throws NullPointerException if any element is null 146 */ 147 public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { 148 return construct(e1, e2, e3, e4, e5, e6, e7); 149 } 150 151 /** 152 * Returns an immutable list containing the given elements, in order. 153 * 154 * @throws NullPointerException if any element is null 155 */ 156 public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { 157 return construct(e1, e2, e3, e4, e5, e6, e7, e8); 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(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { 166 return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9); 167 } 168 169 /** 170 * Returns an immutable list containing the given elements, in order. 171 * 172 * @throws NullPointerException if any element is null 173 */ 174 public static <E> ImmutableList<E> of( 175 E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { 176 return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10); 177 } 178 179 /** 180 * Returns an immutable list containing the given elements, in order. 181 * 182 * @throws NullPointerException if any element is null 183 */ 184 public static <E> ImmutableList<E> of( 185 E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) { 186 return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11); 187 } 188 189 // These go up to eleven. After that, you just get the varargs form, and 190 // whatever warnings might come along with it. :( 191 192 /** 193 * Returns an immutable list containing the given elements, in order. 194 * 195 * <p>The array {@code others} must not be longer than {@code Integer.MAX_VALUE - 12}. 196 * 197 * @throws NullPointerException if any element is null 198 * @since 3.0 (source-compatible since 2.0) 199 */ 200 @SafeVarargs // For Eclipse. For internal javac we have disabled this pointless type of warning. 201 public static <E> ImmutableList<E> of( 202 E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E... others) { 203 checkArgument( 204 others.length <= Integer.MAX_VALUE - 12, 205 "the total number of elements must fit in an int"); 206 Object[] array = new Object[12 + others.length]; 207 array[0] = e1; 208 array[1] = e2; 209 array[2] = e3; 210 array[3] = e4; 211 array[4] = e5; 212 array[5] = e6; 213 array[6] = e7; 214 array[7] = e8; 215 array[8] = e9; 216 array[9] = e10; 217 array[10] = e11; 218 array[11] = e12; 219 System.arraycopy(others, 0, array, 12, others.length); 220 return construct(array); 221 } 222 223 /** 224 * Returns an immutable list containing the given elements, in order. If {@code elements} is a 225 * {@link Collection}, this method behaves exactly as {@link #copyOf(Collection)}; otherwise, it 226 * behaves exactly as {@code copyOf(elements.iterator()}. 227 * 228 * @throws NullPointerException if any of {@code elements} is null 229 */ 230 public static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements) { 231 checkNotNull(elements); // TODO(kevinb): is this here only for GWT? 232 return (elements instanceof Collection) 233 ? copyOf((Collection<? extends E>) elements) 234 : copyOf(elements.iterator()); 235 } 236 237 /** 238 * Returns an immutable list containing the given elements, in order. 239 * 240 * <p>Despite the method name, this method attempts to avoid actually copying the data when it is 241 * safe to do so. The exact circumstances under which a copy will or will not be performed are 242 * undocumented and subject to change. 243 * 244 * <p>Note that if {@code list} is a {@code List<String>}, then {@code ImmutableList.copyOf(list)} 245 * returns an {@code ImmutableList<String>} containing each of the strings in {@code list}, while 246 * ImmutableList.of(list)} returns an {@code ImmutableList<List<String>>} containing one element 247 * (the given list itself). 248 * 249 * <p>This method is safe to use even when {@code elements} is a synchronized or concurrent 250 * collection that is currently being modified by another thread. 251 * 252 * @throws NullPointerException if any of {@code elements} is null 253 */ 254 public static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) { 255 if (elements instanceof ImmutableCollection) { 256 @SuppressWarnings("unchecked") // all supported methods are covariant 257 ImmutableList<E> list = ((ImmutableCollection<E>) elements).asList(); 258 return list.isPartialView() ? ImmutableList.<E>asImmutableList(list.toArray()) : list; 259 } 260 return construct(elements.toArray()); 261 } 262 263 /** 264 * Returns an immutable list containing the given elements, in order. 265 * 266 * @throws NullPointerException if any of {@code elements} is null 267 */ 268 public static <E> ImmutableList<E> copyOf(Iterator<? extends E> elements) { 269 // We special-case for 0 or 1 elements, but going further is madness. 270 if (!elements.hasNext()) { 271 return of(); 272 } 273 E first = elements.next(); 274 if (!elements.hasNext()) { 275 return of(first); 276 } else { 277 return new ImmutableList.Builder<E>().add(first).addAll(elements).build(); 278 } 279 } 280 281 /** 282 * Returns an immutable list containing the given elements, in order. 283 * 284 * @throws NullPointerException if any of {@code elements} is null 285 * @since 3.0 286 */ 287 public static <E> ImmutableList<E> copyOf(E[] elements) { 288 switch (elements.length) { 289 case 0: 290 return of(); 291 case 1: 292 return of(elements[0]); 293 default: 294 return construct(elements.clone()); 295 } 296 } 297 298 /** 299 * Returns an immutable list containing the given elements, sorted according to their natural 300 * order. The sorting algorithm used is stable, so elements that compare as equal will stay in the 301 * order in which they appear in the input. 302 * 303 * <p>If your data has no duplicates, or you wish to deduplicate elements, use {@code 304 * ImmutableSortedSet.copyOf(elements)}; if you want a {@code List} you can use its {@code 305 * asList()} view. 306 * 307 * <p><b>Java 8 users:</b> If you want to convert a {@link java.util.stream.Stream} to a sorted 308 * {@code ImmutableList}, use {@code stream.sorted().collect(toImmutableList())}. 309 * 310 * @throws NullPointerException if any element in the input is null 311 * @since 21.0 312 */ 313 public static <E extends Comparable<? super E>> ImmutableList<E> sortedCopyOf( 314 Iterable<? extends E> elements) { 315 Comparable<?>[] array = Iterables.toArray(elements, new Comparable<?>[0]); 316 checkElementsNotNull((Object[]) array); 317 Arrays.sort(array); 318 return asImmutableList(array); 319 } 320 321 /** 322 * Returns an immutable list containing the given elements, in sorted order relative to the 323 * specified comparator. The sorting algorithm used is stable, so elements that compare as equal 324 * will stay in the order in which they appear in the input. 325 * 326 * <p>If your data has no duplicates, or you wish to deduplicate elements, use {@code 327 * ImmutableSortedSet.copyOf(comparator, elements)}; if you want a {@code List} you can use its 328 * {@code asList()} view. 329 * 330 * <p><b>Java 8 users:</b> If you want to convert a {@link java.util.stream.Stream} to a sorted 331 * {@code ImmutableList}, use {@code stream.sorted(comparator).collect(toImmutableList())}. 332 * 333 * @throws NullPointerException if any element in the input is null 334 * @since 21.0 335 */ 336 public static <E> ImmutableList<E> sortedCopyOf( 337 Comparator<? super E> comparator, Iterable<? extends E> elements) { 338 checkNotNull(comparator); 339 @SuppressWarnings("unchecked") // all supported methods are covariant 340 E[] array = (E[]) Iterables.toArray(elements); 341 checkElementsNotNull(array); 342 Arrays.sort(array, comparator); 343 return asImmutableList(array); 344 } 345 346 /** Views the array as an immutable list. Checks for nulls; does not copy. */ 347 private static <E> ImmutableList<E> construct(Object... elements) { 348 return asImmutableList(checkElementsNotNull(elements)); 349 } 350 351 /** 352 * Views the array as an immutable list. Does not check for nulls; does not copy. 353 * 354 * <p>The array must be internally created. 355 */ 356 static <E> ImmutableList<E> asImmutableList(Object[] elements) { 357 return asImmutableList(elements, elements.length); 358 } 359 360 /** 361 * Views the array as an immutable list. Copies if the specified range does not cover the complete 362 * array. Does not check for nulls. 363 */ 364 static <E> ImmutableList<E> asImmutableList(Object[] elements, int length) { 365 switch (length) { 366 case 0: 367 return of(); 368 case 1: 369 return of((E) elements[0]); 370 default: 371 if (length < elements.length) { 372 elements = Arrays.copyOf(elements, length); 373 } 374 return new RegularImmutableList<E>(elements); 375 } 376 } 377 378 ImmutableList() {} 379 380 // This declaration is needed to make List.iterator() and 381 // ImmutableCollection.iterator() consistent. 382 @Override 383 public UnmodifiableIterator<E> iterator() { 384 return listIterator(); 385 } 386 387 @Override 388 public UnmodifiableListIterator<E> listIterator() { 389 return listIterator(0); 390 } 391 392 @Override 393 public UnmodifiableListIterator<E> listIterator(int index) { 394 return new AbstractIndexedListIterator<E>(size(), index) { 395 @Override 396 protected E get(int index) { 397 return ImmutableList.this.get(index); 398 } 399 }; 400 } 401 402 @Override 403 public void forEach(Consumer<? super E> consumer) { 404 checkNotNull(consumer); 405 int n = size(); 406 for (int i = 0; i < n; i++) { 407 consumer.accept(get(i)); 408 } 409 } 410 411 @Override 412 public int indexOf(@Nullable Object object) { 413 return (object == null) ? -1 : Lists.indexOfImpl(this, object); 414 } 415 416 @Override 417 public int lastIndexOf(@Nullable Object object) { 418 return (object == null) ? -1 : Lists.lastIndexOfImpl(this, object); 419 } 420 421 @Override 422 public boolean contains(@Nullable Object object) { 423 return indexOf(object) >= 0; 424 } 425 426 // constrain the return type to ImmutableList<E> 427 428 /** 429 * Returns an immutable list of the elements between the specified {@code fromIndex}, inclusive, 430 * and {@code toIndex}, exclusive. (If {@code fromIndex} and {@code toIndex} are equal, the empty 431 * immutable list is returned.) 432 */ 433 @Override 434 public ImmutableList<E> subList(int fromIndex, int toIndex) { 435 checkPositionIndexes(fromIndex, toIndex, size()); 436 int length = toIndex - fromIndex; 437 if (length == size()) { 438 return this; 439 } else if (length == 0) { 440 return of(); 441 } else if (length == 1) { 442 return of(get(fromIndex)); 443 } else { 444 return subListUnchecked(fromIndex, toIndex); 445 } 446 } 447 448 /** 449 * Called by the default implementation of {@link #subList} when {@code toIndex - fromIndex > 1}, 450 * after index validation has already been performed. 451 */ 452 ImmutableList<E> subListUnchecked(int fromIndex, int toIndex) { 453 return new SubList(fromIndex, toIndex - fromIndex); 454 } 455 456 class SubList extends ImmutableList<E> { 457 final transient int offset; 458 final transient int length; 459 460 SubList(int offset, int length) { 461 this.offset = offset; 462 this.length = length; 463 } 464 465 @Override 466 public int size() { 467 return length; 468 } 469 470 @Override 471 public E get(int index) { 472 checkElementIndex(index, length); 473 return ImmutableList.this.get(index + offset); 474 } 475 476 @Override 477 public ImmutableList<E> subList(int fromIndex, int toIndex) { 478 checkPositionIndexes(fromIndex, toIndex, length); 479 return ImmutableList.this.subList(fromIndex + offset, toIndex + offset); 480 } 481 482 @Override 483 boolean isPartialView() { 484 return true; 485 } 486 } 487 488 /** 489 * Guaranteed to throw an exception and leave the list unmodified. 490 * 491 * @throws UnsupportedOperationException always 492 * @deprecated Unsupported operation. 493 */ 494 @CanIgnoreReturnValue 495 @Deprecated 496 @Override 497 public final boolean addAll(int index, Collection<? extends E> newElements) { 498 throw new UnsupportedOperationException(); 499 } 500 501 /** 502 * Guaranteed to throw an exception and leave the list unmodified. 503 * 504 * @throws UnsupportedOperationException always 505 * @deprecated Unsupported operation. 506 */ 507 @CanIgnoreReturnValue 508 @Deprecated 509 @Override 510 public final E set(int index, E element) { 511 throw new UnsupportedOperationException(); 512 } 513 514 /** 515 * Guaranteed to throw an exception and leave the list unmodified. 516 * 517 * @throws UnsupportedOperationException always 518 * @deprecated Unsupported operation. 519 */ 520 @Deprecated 521 @Override 522 public final void add(int index, E element) { 523 throw new UnsupportedOperationException(); 524 } 525 526 /** 527 * Guaranteed to throw an exception and leave the list unmodified. 528 * 529 * @throws UnsupportedOperationException always 530 * @deprecated Unsupported operation. 531 */ 532 @CanIgnoreReturnValue 533 @Deprecated 534 @Override 535 public final E remove(int index) { 536 throw new UnsupportedOperationException(); 537 } 538 539 /** 540 * Guaranteed to throw an exception and leave the list unmodified. 541 * 542 * @throws UnsupportedOperationException always 543 * @deprecated Unsupported operation. 544 */ 545 @Deprecated 546 @Override 547 public final void replaceAll(UnaryOperator<E> operator) { 548 throw new UnsupportedOperationException(); 549 } 550 551 /** 552 * Guaranteed to throw an exception and leave the list unmodified. 553 * 554 * @throws UnsupportedOperationException always 555 * @deprecated Unsupported operation. 556 */ 557 @Deprecated 558 @Override 559 public final void sort(Comparator<? super E> c) { 560 throw new UnsupportedOperationException(); 561 } 562 563 /** 564 * Returns this list instance. 565 * 566 * @since 2.0 567 */ 568 @Override 569 public final ImmutableList<E> asList() { 570 return this; 571 } 572 573 @Override 574 public Spliterator<E> spliterator() { 575 return CollectSpliterators.indexed(size(), SPLITERATOR_CHARACTERISTICS, this::get); 576 } 577 578 @Override 579 int copyIntoArray(Object[] dst, int offset) { 580 // this loop is faster for RandomAccess instances, which ImmutableLists are 581 int size = size(); 582 for (int i = 0; i < size; i++) { 583 dst[offset + i] = get(i); 584 } 585 return offset + size; 586 } 587 588 /** 589 * Returns a view of this immutable list in reverse order. For example, {@code ImmutableList.of(1, 590 * 2, 3).reverse()} is equivalent to {@code ImmutableList.of(3, 2, 1)}. 591 * 592 * @return a view of this immutable list in reverse order 593 * @since 7.0 594 */ 595 public ImmutableList<E> reverse() { 596 return (size() <= 1) ? this : new ReverseImmutableList<E>(this); 597 } 598 599 private static class ReverseImmutableList<E> extends ImmutableList<E> { 600 private final transient ImmutableList<E> forwardList; 601 602 ReverseImmutableList(ImmutableList<E> backingList) { 603 this.forwardList = backingList; 604 } 605 606 private int reverseIndex(int index) { 607 return (size() - 1) - index; 608 } 609 610 private int reversePosition(int index) { 611 return size() - index; 612 } 613 614 @Override 615 public ImmutableList<E> reverse() { 616 return forwardList; 617 } 618 619 @Override 620 public boolean contains(@Nullable Object object) { 621 return forwardList.contains(object); 622 } 623 624 @Override 625 public int indexOf(@Nullable Object object) { 626 int index = forwardList.lastIndexOf(object); 627 return (index >= 0) ? reverseIndex(index) : -1; 628 } 629 630 @Override 631 public int lastIndexOf(@Nullable Object object) { 632 int index = forwardList.indexOf(object); 633 return (index >= 0) ? reverseIndex(index) : -1; 634 } 635 636 @Override 637 public ImmutableList<E> subList(int fromIndex, int toIndex) { 638 checkPositionIndexes(fromIndex, toIndex, size()); 639 return forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex)).reverse(); 640 } 641 642 @Override 643 public E get(int index) { 644 checkElementIndex(index, size()); 645 return forwardList.get(reverseIndex(index)); 646 } 647 648 @Override 649 public int size() { 650 return forwardList.size(); 651 } 652 653 @Override 654 boolean isPartialView() { 655 return forwardList.isPartialView(); 656 } 657 } 658 659 @Override 660 public boolean equals(@Nullable Object obj) { 661 return Lists.equalsImpl(this, obj); 662 } 663 664 @Override 665 public int hashCode() { 666 int hashCode = 1; 667 int n = size(); 668 for (int i = 0; i < n; i++) { 669 hashCode = 31 * hashCode + get(i).hashCode(); 670 671 hashCode = ~~hashCode; 672 // needed to deal with GWT integer overflow 673 } 674 return hashCode; 675 } 676 677 /* 678 * Serializes ImmutableLists as their logical contents. This ensures that 679 * implementation types do not leak into the serialized representation. 680 */ 681 static class SerializedForm implements Serializable { 682 final Object[] elements; 683 684 SerializedForm(Object[] elements) { 685 this.elements = elements; 686 } 687 688 Object readResolve() { 689 return copyOf(elements); 690 } 691 692 private static final long serialVersionUID = 0; 693 } 694 695 private void readObject(ObjectInputStream stream) throws InvalidObjectException { 696 throw new InvalidObjectException("Use SerializedForm"); 697 } 698 699 @Override 700 Object writeReplace() { 701 return new SerializedForm(toArray()); 702 } 703 704 /** 705 * Returns a new builder. The generated builder is equivalent to the builder created by the {@link 706 * Builder} constructor. 707 */ 708 public static <E> Builder<E> builder() { 709 return new Builder<E>(); 710 } 711 712 /** 713 * Returns a new builder, expecting the specified number of elements to be added. 714 * 715 * <p>If {@code expectedSize} is exactly the number of elements added to the builder before {@link 716 * Builder#build} is called, the builder is likely to perform better than an unsized {@link 717 * #builder()} would have. 718 * 719 * <p>It is not specified if any performance benefits apply if {@code expectedSize} is close to, 720 * but not exactly, the number of elements added to the builder. 721 * 722 * @since 23.1 723 */ 724 @Beta 725 public static <E> Builder<E> builderWithExpectedSize(int expectedSize) { 726 checkNonnegative(expectedSize, "expectedSize"); 727 return new ImmutableList.Builder<E>(expectedSize); 728 } 729 730 /** 731 * A builder for creating immutable list instances, especially {@code public static final} lists 732 * ("constant lists"). Example: 733 * 734 * <pre>{@code 735 * public static final ImmutableList<Color> GOOGLE_COLORS 736 * = new ImmutableList.Builder<Color>() 737 * .addAll(WEBSAFE_COLORS) 738 * .add(new Color(0, 191, 255)) 739 * .build(); 740 * }</pre> 741 * 742 * <p>Elements appear in the resulting list in the same order they were added to the builder. 743 * 744 * <p>Builder instances can be reused; it is safe to call {@link #build} multiple times to build 745 * multiple lists in series. Each new list contains all the elements of the ones created before 746 * it. 747 * 748 * @since 2.0 749 */ 750 public static final class Builder<E> extends ImmutableCollection.Builder<E> { 751 @VisibleForTesting Object[] contents; 752 private int size; 753 private boolean forceCopy; 754 755 /** 756 * Creates a new builder. The returned builder is equivalent to the builder generated by {@link 757 * ImmutableList#builder}. 758 */ 759 public Builder() { 760 this(DEFAULT_INITIAL_CAPACITY); 761 } 762 763 Builder(int capacity) { 764 this.contents = new Object[capacity]; 765 this.size = 0; 766 } 767 768 private void getReadyToExpandTo(int minCapacity) { 769 if (contents.length < minCapacity) { 770 this.contents = Arrays.copyOf(contents, expandedCapacity(contents.length, minCapacity)); 771 forceCopy = false; 772 } else if (forceCopy) { 773 contents = Arrays.copyOf(contents, contents.length); 774 forceCopy = false; 775 } 776 } 777 778 /** 779 * Adds {@code element} to the {@code ImmutableList}. 780 * 781 * @param element the element to add 782 * @return this {@code Builder} object 783 * @throws NullPointerException if {@code element} is null 784 */ 785 @CanIgnoreReturnValue 786 @Override 787 public Builder<E> add(E element) { 788 checkNotNull(element); 789 getReadyToExpandTo(size + 1); 790 contents[size++] = element; 791 return this; 792 } 793 794 /** 795 * Adds each element of {@code elements} to the {@code ImmutableList}. 796 * 797 * @param elements the {@code Iterable} to add to the {@code ImmutableList} 798 * @return this {@code Builder} object 799 * @throws NullPointerException if {@code elements} is null or contains a null element 800 */ 801 @CanIgnoreReturnValue 802 @Override 803 public Builder<E> add(E... elements) { 804 checkElementsNotNull(elements); 805 add(elements, elements.length); 806 return this; 807 } 808 809 private void add(Object[] elements, int n) { 810 getReadyToExpandTo(size + n); 811 System.arraycopy(elements, 0, contents, size, n); 812 size += n; 813 } 814 815 /** 816 * Adds each element of {@code elements} to the {@code ImmutableList}. 817 * 818 * @param elements the {@code Iterable} to add to the {@code ImmutableList} 819 * @return this {@code Builder} object 820 * @throws NullPointerException if {@code elements} is null or contains a null element 821 */ 822 @CanIgnoreReturnValue 823 @Override 824 public Builder<E> addAll(Iterable<? extends E> elements) { 825 checkNotNull(elements); 826 if (elements instanceof Collection) { 827 Collection<?> collection = (Collection<?>) elements; 828 getReadyToExpandTo(size + collection.size()); 829 if (collection instanceof ImmutableCollection) { 830 ImmutableCollection<?> immutableCollection = (ImmutableCollection<?>) collection; 831 size = immutableCollection.copyIntoArray(contents, size); 832 return this; 833 } 834 } 835 super.addAll(elements); 836 return this; 837 } 838 839 /** 840 * Adds each element of {@code elements} to the {@code ImmutableList}. 841 * 842 * @param elements the {@code Iterable} to add to the {@code ImmutableList} 843 * @return this {@code Builder} object 844 * @throws NullPointerException if {@code elements} is null or contains a null element 845 */ 846 @CanIgnoreReturnValue 847 @Override 848 public Builder<E> addAll(Iterator<? extends E> elements) { 849 super.addAll(elements); 850 return this; 851 } 852 853 @CanIgnoreReturnValue 854 Builder<E> combine(Builder<E> builder) { 855 checkNotNull(builder); 856 add(builder.contents, builder.size); 857 return this; 858 } 859 860 /** 861 * Returns a newly-created {@code ImmutableList} based on the contents of the {@code Builder}. 862 */ 863 @Override 864 public ImmutableList<E> build() { 865 forceCopy = true; 866 return asImmutableList(contents, size); 867 } 868 } 869}