• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.base.Preconditions;
23 
24 import java.io.InvalidObjectException;
25 import java.io.ObjectInputStream;
26 import java.io.Serializable;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.RandomAccess;
33 
34 import javax.annotation.Nullable;
35 
36 /**
37  * A high-performance, immutable, random-access {@code List} implementation.
38  * Does not permit null elements.
39  *
40  * <p>Unlike {@link Collections#unmodifiableList}, which is a <i>view</i> of a
41  * separate collection that can still change, an instance of {@code
42  * ImmutableList} contains its own private data and will <i>never</i> change.
43  * {@code ImmutableList} is convenient for {@code public static final} lists
44  * ("constant lists") and also lets you easily make a "defensive copy" of a list
45  * provided to your class by a caller.
46  *
47  * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
48  * it has no public or protected constructors. Thus, instances of this type are
49  * guaranteed to be immutable.
50  *
51  * @see ImmutableMap
52  * @see ImmutableSet
53  * @author Kevin Bourrillion
54  * @since 2.0 (imported from Google Collections Library)
55  */
56 @GwtCompatible(serializable = true, emulated = true)
57 @SuppressWarnings("serial") // we're overriding default serialization
58 public abstract class ImmutableList<E> extends ImmutableCollection<E>
59     implements List<E>, RandomAccess {
60   /**
61    * Returns the empty immutable list. This set behaves and performs comparably
62    * to {@link Collections#emptyList}, and is preferable mainly for consistency
63    * and maintainability of your code.
64    */
65   // Casting to any type is safe because the list will never hold any elements.
66   @SuppressWarnings("unchecked")
of()67   public static <E> ImmutableList<E> of() {
68     return (ImmutableList<E>) EmptyImmutableList.INSTANCE;
69   }
70 
71   /**
72    * Returns an immutable list containing a single element. This list behaves
73    * and performs comparably to {@link Collections#singleton}, but will not
74    * accept a null element. It is preferable mainly for consistency and
75    * maintainability of your code.
76    *
77    * @throws NullPointerException if {@code element} is null
78    */
of(E element)79   public static <E> ImmutableList<E> of(E element) {
80     return new SingletonImmutableList<E>(element);
81   }
82 
83   /**
84    * Returns an immutable list containing the given elements, in order.
85    *
86    * @throws NullPointerException if any element is null
87    */
of(E e1, E e2)88   public static <E> ImmutableList<E> of(E e1, E e2) {
89     return construct(e1, e2);
90   }
91 
92   /**
93    * Returns an immutable list containing the given elements, in order.
94    *
95    * @throws NullPointerException if any element is null
96    */
of(E e1, E e2, E e3)97   public static <E> ImmutableList<E> of(E e1, E e2, E e3) {
98     return construct(e1, e2, e3);
99   }
100 
101   /**
102    * Returns an immutable list containing the given elements, in order.
103    *
104    * @throws NullPointerException if any element is null
105    */
of(E e1, E e2, E e3, E e4)106   public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4) {
107     return construct(e1, e2, e3, e4);
108   }
109 
110   /**
111    * Returns an immutable list containing the given elements, in order.
112    *
113    * @throws NullPointerException if any element is null
114    */
of(E e1, E e2, E e3, E e4, E e5)115   public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5) {
116     return construct(e1, e2, e3, e4, e5);
117   }
118 
119   /**
120    * Returns an immutable list containing the given elements, in order.
121    *
122    * @throws NullPointerException if any element is null
123    */
of(E e1, E e2, E e3, E e4, E e5, E e6)124   public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
125     return construct(e1, e2, e3, e4, e5, e6);
126   }
127 
128   /**
129    * Returns an immutable list containing the given elements, in order.
130    *
131    * @throws NullPointerException if any element is null
132    */
of( E e1, E e2, E e3, E e4, E e5, E e6, E e7)133   public static <E> ImmutableList<E> of(
134       E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
135     return construct(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    */
of( E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8)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 construct(e1, e2, e3, e4, e5, e6, e7, e8);
146   }
147 
148   /**
149    * Returns an immutable list containing the given elements, in order.
150    *
151    * @throws NullPointerException if any element is null
152    */
of( E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9)153   public static <E> ImmutableList<E> of(
154       E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
155     return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9);
156   }
157 
158   /**
159    * Returns an immutable list containing the given elements, in order.
160    *
161    * @throws NullPointerException if any element is null
162    */
of( E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)163   public static <E> ImmutableList<E> of(
164       E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
165     return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
166   }
167 
168   /**
169    * Returns an immutable list containing the given elements, in order.
170    *
171    * @throws NullPointerException if any element is null
172    */
of( E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11)173   public static <E> ImmutableList<E> of(
174       E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) {
175     return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11);
176   }
177 
178   // These go up to eleven. After that, you just get the varargs form, and
179   // whatever warnings might come along with it. :(
180 
181   /**
182    * Returns an immutable list containing the given elements, in order.
183    *
184    * @throws NullPointerException if any element is null
185    * @since 3.0 (source-compatible since 2.0)
186    */
of( 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)187   public static <E> ImmutableList<E> of(
188       E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12,
189       E... others) {
190     Object[] array = new Object[12 + others.length];
191     array[0] = e1;
192     array[1] = e2;
193     array[2] = e3;
194     array[3] = e4;
195     array[4] = e5;
196     array[5] = e6;
197     array[6] = e7;
198     array[7] = e8;
199     array[8] = e9;
200     array[9] = e10;
201     array[10] = e11;
202     array[11] = e12;
203     System.arraycopy(others, 0, array, 12, others.length);
204     return construct(array);
205   }
206 
207   /**
208    * Returns an immutable list containing the given elements, in order. If
209    * {@code elements} is a {@link Collection}, this method behaves exactly as
210    * {@link #copyOf(Collection)}; otherwise, it behaves exactly as {@code
211    * copyOf(elements.iterator()}.
212    *
213    * @throws NullPointerException if any of {@code elements} is null
214    */
copyOf(Iterable<? extends E> elements)215   public static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements) {
216     checkNotNull(elements); // TODO(kevinb): is this here only for GWT?
217     return (elements instanceof Collection)
218       ? copyOf(Collections2.cast(elements))
219       : copyOf(elements.iterator());
220   }
221 
222   /**
223    * Returns an immutable list containing the given elements, in order.
224    *
225    * <p>Despite the method name, this method attempts to avoid actually copying
226    * the data when it is safe to do so. The exact circumstances under which a
227    * copy will or will not be performed are undocumented and subject to change.
228    *
229    * <p>Note that if {@code list} is a {@code List<String>}, then {@code
230    * ImmutableList.copyOf(list)} returns an {@code ImmutableList<String>}
231    * containing each of the strings in {@code list}, while
232    * ImmutableList.of(list)} returns an {@code ImmutableList<List<String>>}
233    * containing one element (the given list itself).
234    *
235    * <p>This method is safe to use even when {@code elements} is a synchronized
236    * or concurrent collection that is currently being modified by another
237    * thread.
238    *
239    * @throws NullPointerException if any of {@code elements} is null
240    */
copyOf(Collection<? extends E> elements)241   public static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) {
242     if (elements instanceof ImmutableCollection) {
243       @SuppressWarnings("unchecked") // all supported methods are covariant
244       ImmutableList<E> list = ((ImmutableCollection<E>) elements).asList();
245       return list.isPartialView() ? copyFromCollection(list) : list;
246     }
247     return copyFromCollection(elements);
248   }
249 
250   /**
251    * Returns an immutable list containing the given elements, in order.
252    *
253    * @throws NullPointerException if any of {@code elements} is null
254    */
copyOf(Iterator<? extends E> elements)255   public static <E> ImmutableList<E> copyOf(Iterator<? extends E> elements) {
256     return copyFromCollection(Lists.newArrayList(elements));
257   }
258 
259   /**
260    * Returns an immutable list containing the given elements, in order.
261    *
262    * @throws NullPointerException if any of {@code elements} is null
263    * @since 3.0
264    */
copyOf(E[] elements)265   public static <E> ImmutableList<E> copyOf(E[] elements) {
266     switch (elements.length) {
267       case 0:
268         return ImmutableList.of();
269       case 1:
270         return new SingletonImmutableList<E>(elements[0]);
271       default:
272         return construct(elements.clone());
273     }
274   }
275 
copyFromCollection( Collection<? extends E> collection)276   private static <E> ImmutableList<E> copyFromCollection(
277       Collection<? extends E> collection) {
278     Object[] elements = collection.toArray();
279     switch (elements.length) {
280       case 0:
281         return of();
282       case 1:
283         @SuppressWarnings("unchecked") // collection had only Es in it
284         ImmutableList<E> list = new SingletonImmutableList<E>((E) elements[0]);
285         return list;
286       default:
287         // safe to use the array without copying it
288         // as specified by Collection.toArray().
289         return construct(elements);
290     }
291   }
292 
293   /** {@code elements} has to be internally created array. */
construct(Object... elements)294   private static <E> ImmutableList<E> construct(Object... elements) {
295     for (int i = 0; i < elements.length; i++) {
296       checkElementNotNull(elements[i], i);
297     }
298     return new RegularImmutableList<E>(elements);
299   }
300 
301   // We do this instead of Preconditions.checkNotNull to save boxing and array
302   // creation cost.
checkElementNotNull(Object element, int index)303   private static Object checkElementNotNull(Object element, int index) {
304     if (element == null) {
305       throw new NullPointerException("at index " + index);
306     }
307     return element;
308   }
309 
ImmutableList()310   ImmutableList() {}
311 
312   // This declaration is needed to make List.iterator() and
313   // ImmutableCollection.iterator() consistent.
iterator()314   @Override public UnmodifiableIterator<E> iterator() {
315     return listIterator();
316   }
317 
listIterator()318   @Override public UnmodifiableListIterator<E> listIterator() {
319     return listIterator(0);
320   }
321 
listIterator(int index)322   @Override public abstract UnmodifiableListIterator<E> listIterator(int index);
323 
324   // Mark these two methods with @Nullable
325 
326   @Override
indexOf(@ullable Object object)327   public abstract int indexOf(@Nullable Object object);
328 
329   @Override
lastIndexOf(@ullable Object object)330   public abstract int lastIndexOf(@Nullable Object object);
331 
332   // constrain the return type to ImmutableList<E>
333 
334   /**
335    * Returns an immutable list of the elements between the specified {@code
336    * fromIndex}, inclusive, and {@code toIndex}, exclusive. (If {@code
337    * fromIndex} and {@code toIndex} are equal, the empty immutable list is
338    * returned.)
339    */
340   @Override
subList(int fromIndex, int toIndex)341   public abstract ImmutableList<E> subList(int fromIndex, int toIndex);
342 
343   /**
344    * Guaranteed to throw an exception and leave the list unmodified.
345    *
346    * @throws UnsupportedOperationException always
347    */
348   @Override
addAll(int index, Collection<? extends E> newElements)349   public final boolean addAll(int index, Collection<? extends E> newElements) {
350     throw new UnsupportedOperationException();
351   }
352 
353   /**
354    * Guaranteed to throw an exception and leave the list unmodified.
355    *
356    * @throws UnsupportedOperationException always
357    */
358   @Override
set(int index, E element)359   public final E set(int index, E element) {
360     throw new UnsupportedOperationException();
361   }
362 
363   /**
364    * Guaranteed to throw an exception and leave the list unmodified.
365    *
366    * @throws UnsupportedOperationException always
367    */
368   @Override
add(int index, E element)369   public final void add(int index, E element) {
370     throw new UnsupportedOperationException();
371   }
372 
373   /**
374    * Guaranteed to throw an exception and leave the list unmodified.
375    *
376    * @throws UnsupportedOperationException always
377    */
378   @Override
remove(int index)379   public final E remove(int index) {
380     throw new UnsupportedOperationException();
381   }
382 
383   /**
384    * Returns this list instance.
385    *
386    * @since 2.0
387    */
asList()388   @Override public ImmutableList<E> asList() {
389     return this;
390   }
391 
392   /**
393    * Returns a view of this immutable list in reverse order. For example, {@code
394    * ImmutableList.of(1, 2, 3).reverse()} is equivalent to {@code
395    * ImmutableList.of(3, 2, 1)}.
396    *
397    * @return a view of this immutable list in reverse order
398    * @since 7.0
399    */
reverse()400   public ImmutableList<E> reverse() {
401     return new ReverseImmutableList<E>(this);
402   }
403 
404   private static class ReverseImmutableList<E> extends ImmutableList<E> {
405     private transient final ImmutableList<E> forwardList;
406     private transient final int size;
407 
ReverseImmutableList(ImmutableList<E> backingList)408     ReverseImmutableList(ImmutableList<E> backingList) {
409       this.forwardList = backingList;
410       this.size = backingList.size();
411     }
412 
reverseIndex(int index)413     private int reverseIndex(int index) {
414       return (size - 1) - index;
415     }
416 
reversePosition(int index)417     private int reversePosition(int index) {
418       return size - index;
419     }
420 
reverse()421     @Override public ImmutableList<E> reverse() {
422       return forwardList;
423     }
424 
contains(@ullable Object object)425     @Override public boolean contains(@Nullable Object object) {
426       return forwardList.contains(object);
427     }
428 
containsAll(Collection<?> targets)429     @Override public boolean containsAll(Collection<?> targets) {
430       return forwardList.containsAll(targets);
431     }
432 
indexOf(@ullable Object object)433     @Override public int indexOf(@Nullable Object object) {
434       int index = forwardList.lastIndexOf(object);
435       return (index >= 0) ? reverseIndex(index) : -1;
436     }
437 
lastIndexOf(@ullable Object object)438     @Override public int lastIndexOf(@Nullable Object object) {
439       int index = forwardList.indexOf(object);
440       return (index >= 0) ? reverseIndex(index) : -1;
441     }
442 
subList(int fromIndex, int toIndex)443     @Override public ImmutableList<E> subList(int fromIndex, int toIndex) {
444       Preconditions.checkPositionIndexes(fromIndex, toIndex, size);
445       return forwardList.subList(
446           reversePosition(toIndex), reversePosition(fromIndex)).reverse();
447     }
448 
get(int index)449     @Override public E get(int index) {
450       Preconditions.checkElementIndex(index, size);
451       return forwardList.get(reverseIndex(index));
452     }
453 
listIterator(int index)454     @Override public UnmodifiableListIterator<E> listIterator(int index) {
455       Preconditions.checkPositionIndex(index, size);
456       final UnmodifiableListIterator<E> forward =
457           forwardList.listIterator(reversePosition(index));
458       return new UnmodifiableListIterator<E>() {
459         @Override public boolean hasNext() {
460           return forward.hasPrevious();
461         }
462 
463         @Override public boolean hasPrevious() {
464           return forward.hasNext();
465         }
466 
467         @Override public E next() {
468           return forward.previous();
469         }
470 
471         @Override public int nextIndex() {
472           return reverseIndex(forward.previousIndex());
473         }
474 
475         @Override public E previous() {
476           return forward.next();
477         }
478 
479         @Override public int previousIndex() {
480           return reverseIndex(forward.nextIndex());
481         }
482       };
483     }
484 
size()485     @Override public int size() {
486       return size;
487     }
488 
isEmpty()489     @Override public boolean isEmpty() {
490       return forwardList.isEmpty();
491     }
492 
isPartialView()493     @Override boolean isPartialView() {
494       return forwardList.isPartialView();
495     }
496   }
497 
498   @Override public boolean equals(Object obj) {
499     return Lists.equalsImpl(this, obj);
500   }
501 
502   @Override public int hashCode() {
503     return Lists.hashCodeImpl(this);
504   }
505 
506   /*
507    * Serializes ImmutableLists as their logical contents. This ensures that
508    * implementation types do not leak into the serialized representation.
509    */
510   private static class SerializedForm implements Serializable {
511     final Object[] elements;
512     SerializedForm(Object[] elements) {
513       this.elements = elements;
514     }
515     Object readResolve() {
516       return copyOf(elements);
517     }
518     private static final long serialVersionUID = 0;
519   }
520 
521   private void readObject(ObjectInputStream stream)
522       throws InvalidObjectException {
523     throw new InvalidObjectException("Use SerializedForm");
524   }
525 
526   @Override Object writeReplace() {
527     return new SerializedForm(toArray());
528   }
529 
530   /**
531    * Returns a new builder. The generated builder is equivalent to the builder
532    * created by the {@link Builder} constructor.
533    */
534   public static <E> Builder<E> builder() {
535     return new Builder<E>();
536   }
537 
538   /**
539    * A builder for creating immutable list instances, especially {@code public
540    * static final} lists ("constant lists"). Example: <pre>   {@code
541    *
542    *   public static final ImmutableList<Color> GOOGLE_COLORS
543    *       = new ImmutableList.Builder<Color>()
544    *           .addAll(WEBSAFE_COLORS)
545    *           .add(new Color(0, 191, 255))
546    *           .build();}</pre>
547    *
548    * Builder instances can be reused; it is safe to call {@link #build} multiple
549    * times to build multiple lists in series. Each new list contains all the
550    * elements of the ones created before it.
551    *
552    * @since 2.0 (imported from Google Collections Library)
553    */
554   public static final class Builder<E> extends ImmutableCollection.Builder<E> {
555     private final ArrayList<E> contents = Lists.newArrayList();
556 
557     /**
558      * Creates a new builder. The returned builder is equivalent to the builder
559      * generated by {@link ImmutableList#builder}.
560      */
561     public Builder() {}
562 
563     /**
564      * Adds {@code element} to the {@code ImmutableList}.
565      *
566      * @param element the element to add
567      * @return this {@code Builder} object
568      * @throws NullPointerException if {@code element} is null
569      */
570     @Override public Builder<E> add(E element) {
571       contents.add(checkNotNull(element));
572       return this;
573     }
574 
575     /**
576      * Adds each element of {@code elements} to the {@code ImmutableList}.
577      *
578      * @param elements the {@code Iterable} to add to the {@code ImmutableList}
579      * @return this {@code Builder} object
580      * @throws NullPointerException if {@code elements} is null or contains a
581      *     null element
582      */
583     @Override public Builder<E> addAll(Iterable<? extends E> elements) {
584       if (elements instanceof Collection) {
585         Collection<?> collection = (Collection<?>) elements;
586         contents.ensureCapacity(contents.size() + collection.size());
587       }
588       super.addAll(elements);
589       return this;
590     }
591 
592     /**
593      * Adds each element of {@code elements} to the {@code ImmutableList}.
594      *
595      * @param elements the {@code Iterable} to add to the {@code ImmutableList}
596      * @return this {@code Builder} object
597      * @throws NullPointerException if {@code elements} is null or contains a
598      *     null element
599      */
600     @Override public Builder<E> add(E... elements) {
601       contents.ensureCapacity(contents.size() + elements.length);
602       super.add(elements);
603       return this;
604     }
605 
606     /**
607      * Adds each element of {@code elements} to the {@code ImmutableList}.
608      *
609      * @param elements the {@code Iterable} to add to the {@code ImmutableList}
610      * @return this {@code Builder} object
611      * @throws NullPointerException if {@code elements} is null or contains a
612      *     null element
613      */
614     @Override public Builder<E> addAll(Iterator<? extends E> elements) {
615       super.addAll(elements);
616       return this;
617     }
618 
619     /**
620      * Returns a newly-created {@code ImmutableList} based on the contents of
621      * the {@code Builder}.
622      */
623     @Override public ImmutableList<E> build() {
624       return copyOf(contents);
625     }
626   }
627 }
628