Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2008 Google Inc.
      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 com.google.common.annotations.GwtCompatible;
     20 import static com.google.common.base.Preconditions.checkNotNull;
     21 
     22 import java.io.Serializable;
     23 import java.util.Collection;
     24 import java.util.Iterator;
     25 
     26 import javax.annotation.Nullable;
     27 
     28 /**
     29  * An immutable collection. Does not permit null elements.
     30  *
     31  * <p>In addition to the {@link Collection} methods, this class has an {@link
     32  * #asList()} method, which returns a list view of the collection's elements.
     33  *
     34  * <p><b>Note</b>: Although this class is not final, it cannot be subclassed
     35  * outside of this package as it has no public or protected constructors. Thus,
     36  * instances of this type are guaranteed to be immutable.
     37  *
     38  * @author Jesse Wilson
     39  * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library)
     40  */
     41 @GwtCompatible
     42 @SuppressWarnings("serial") // we're overriding default serialization
     43 public abstract class ImmutableCollection<E>
     44     implements Collection<E>, Serializable {
     45   static final ImmutableCollection<Object> EMPTY_IMMUTABLE_COLLECTION
     46       = new EmptyImmutableCollection();
     47 
     48   ImmutableCollection() {}
     49 
     50   /**
     51    * Returns an unmodifiable iterator across the elements in this collection.
     52    */
     53   public abstract UnmodifiableIterator<E> iterator();
     54 
     55   public Object[] toArray() {
     56     Object[] newArray = new Object[size()];
     57     return toArray(newArray);
     58   }
     59 
     60   public <T> T[] toArray(T[] other) {
     61     int size = size();
     62     if (other.length < size) {
     63       other = ObjectArrays.newArray(other, size);
     64     } else if (other.length > size) {
     65       other[size] = null;
     66     }
     67 
     68     // Writes will produce ArrayStoreException when the toArray() doc requires.
     69     Object[] otherAsObjectArray = other;
     70     int index = 0;
     71     for (E element : this) {
     72       otherAsObjectArray[index++] = element;
     73     }
     74     return other;
     75   }
     76 
     77   public boolean contains(@Nullable Object object) {
     78     if (object == null) {
     79       return false;
     80     }
     81     for (E element : this) {
     82       if (element.equals(object)) {
     83         return true;
     84       }
     85     }
     86     return false;
     87   }
     88 
     89   public boolean containsAll(Collection<?> targets) {
     90     for (Object target : targets) {
     91       if (!contains(target)) {
     92         return false;
     93       }
     94     }
     95     return true;
     96   }
     97 
     98   public boolean isEmpty() {
     99     return size() == 0;
    100   }
    101 
    102   @Override public String toString() {
    103     StringBuilder sb = new StringBuilder(size() * 16).append('[');
    104     Collections2.standardJoiner.appendTo(sb, this);
    105     return sb.append(']').toString();
    106   }
    107 
    108   /**
    109    * Guaranteed to throw an exception and leave the collection unmodified.
    110    *
    111    * @throws UnsupportedOperationException always
    112    */
    113   public final boolean add(E e) {
    114     throw new UnsupportedOperationException();
    115   }
    116 
    117   /**
    118    * Guaranteed to throw an exception and leave the collection unmodified.
    119    *
    120    * @throws UnsupportedOperationException always
    121    */
    122   public final boolean remove(Object object) {
    123     throw new UnsupportedOperationException();
    124   }
    125 
    126   /**
    127    * Guaranteed to throw an exception and leave the collection unmodified.
    128    *
    129    * @throws UnsupportedOperationException always
    130    */
    131   public final boolean addAll(Collection<? extends E> newElements) {
    132     throw new UnsupportedOperationException();
    133   }
    134 
    135   /**
    136    * Guaranteed to throw an exception and leave the collection unmodified.
    137    *
    138    * @throws UnsupportedOperationException always
    139    */
    140   public final boolean removeAll(Collection<?> oldElements) {
    141     throw new UnsupportedOperationException();
    142   }
    143 
    144   /**
    145    * Guaranteed to throw an exception and leave the collection unmodified.
    146    *
    147    * @throws UnsupportedOperationException always
    148    */
    149   public final boolean retainAll(Collection<?> elementsToKeep) {
    150     throw new UnsupportedOperationException();
    151   }
    152 
    153   /**
    154    * Guaranteed to throw an exception and leave the collection unmodified.
    155    *
    156    * @throws UnsupportedOperationException always
    157    */
    158   public final void clear() {
    159     throw new UnsupportedOperationException();
    160   }
    161 
    162   // TODO: Restructure code so ImmutableList doesn't contain this variable,
    163   // which it doesn't use.
    164   private transient ImmutableList<E> asList;
    165 
    166   /**
    167    * Returns a list view of the collection.
    168    *
    169    * @since 2010.01.04 <b>tentative</b>
    170    */
    171   public ImmutableList<E> asList() {
    172     ImmutableList<E> list = asList;
    173     return (list == null) ? (asList = createAsList()) : list;
    174   }
    175 
    176   ImmutableList<E> createAsList() {
    177     switch (size()) {
    178       case 0:
    179         return ImmutableList.of();
    180       case 1:
    181         return ImmutableList.of(iterator().next());
    182       default:
    183         return new ImmutableAsList<E>(toArray(), this);
    184     }
    185   }
    186 
    187   private static class EmptyImmutableCollection
    188       extends ImmutableCollection<Object> {
    189     public int size() {
    190       return 0;
    191     }
    192 
    193     @Override public boolean isEmpty() {
    194       return true;
    195     }
    196 
    197     @Override public boolean contains(@Nullable Object object) {
    198       return false;
    199     }
    200 
    201     @Override public UnmodifiableIterator<Object> iterator() {
    202       return Iterators.EMPTY_ITERATOR;
    203     }
    204 
    205     private static final Object[] EMPTY_ARRAY = new Object[0];
    206 
    207     @Override public Object[] toArray() {
    208       return EMPTY_ARRAY;
    209     }
    210 
    211     @Override public <T> T[] toArray(T[] array) {
    212       if (array.length > 0) {
    213         array[0] = null;
    214       }
    215       return array;
    216     }
    217   }
    218 
    219   private static class ArrayImmutableCollection<E>
    220       extends ImmutableCollection<E> {
    221     private final E[] elements;
    222 
    223     ArrayImmutableCollection(E[] elements) {
    224       this.elements = elements;
    225     }
    226 
    227     public int size() {
    228       return elements.length;
    229     }
    230 
    231     @Override public boolean isEmpty() {
    232       return false;
    233     }
    234 
    235     @Override public UnmodifiableIterator<E> iterator() {
    236       return Iterators.forArray(elements);
    237     }
    238   }
    239 
    240   /*
    241    * Serializes ImmutableCollections as their logical contents. This ensures
    242    * that implementation types do not leak into the serialized representation.
    243    */
    244   private static class SerializedForm implements Serializable {
    245     final Object[] elements;
    246     SerializedForm(Object[] elements) {
    247       this.elements = elements;
    248     }
    249     Object readResolve() {
    250       return elements.length == 0
    251           ? EMPTY_IMMUTABLE_COLLECTION
    252           : new ArrayImmutableCollection<Object>(Platform.clone(elements));
    253     }
    254     private static final long serialVersionUID = 0;
    255   }
    256 
    257   Object writeReplace() {
    258     return new SerializedForm(toArray());
    259   }
    260 
    261   /**
    262    * Abstract base class for builders of {@link ImmutableCollection} types.
    263    */
    264   abstract static class Builder<E> {
    265     /**
    266      * Adds {@code element} to the {@code ImmutableCollection} being built.
    267      *
    268      * <p>Note that each builder class covariantly returns its own type from
    269      * this method.
    270      *
    271      * @param element the element to add
    272      * @return this {@code Builder} instance
    273      * @throws NullPointerException if {@code element} is null
    274      */
    275     public abstract Builder<E> add(E element);
    276 
    277     /**
    278      * Adds each element of {@code elements} to the {@code ImmutableCollection}
    279      * being built.
    280      *
    281      * <p>Note that each builder class overrides this method in order to
    282      * covariantly return its own type.
    283      *
    284      * @param elements the elements to add
    285      * @return this {@code Builder} instance
    286      * @throws NullPointerException if {@code elements} is null or contains a
    287      *     null element
    288      */
    289     public Builder<E> add(E... elements) {
    290       checkNotNull(elements); // for GWT
    291       for (E element : elements) {
    292         add(element);
    293       }
    294       return this;
    295     }
    296 
    297     /**
    298      * Adds each element of {@code elements} to the {@code ImmutableCollection}
    299      * being built.
    300      *
    301      * <p>Note that each builder class overrides this method in order to
    302      * covariantly return its own type.
    303      *
    304      * @param elements the elements to add
    305      * @return this {@code Builder} instance
    306      * @throws NullPointerException if {@code elements} is null or contains a
    307      *     null element
    308      */
    309     public Builder<E> addAll(Iterable<? extends E> elements) {
    310       checkNotNull(elements); // for GWT
    311       for (E element : elements) {
    312         add(element);
    313       }
    314       return this;
    315     }
    316 
    317     /**
    318      * Adds each element of {@code elements} to the {@code ImmutableCollection}
    319      * being built.
    320      *
    321      * <p>Note that each builder class overrides this method in order to
    322      * covariantly return its own type.
    323      *
    324      * @param elements the elements to add
    325      * @return this {@code Builder} instance
    326      * @throws NullPointerException if {@code elements} is null or contains a
    327      *     null element
    328      */
    329     public Builder<E> addAll(Iterator<? extends E> elements) {
    330       checkNotNull(elements); // for GWT
    331       while (elements.hasNext()) {
    332         add(elements.next());
    333       }
    334       return this;
    335     }
    336 
    337     /**
    338      * Returns a newly-created {@code ImmutableCollection} of the appropriate
    339      * type, containing the elements provided to this builder.
    340      *
    341      * <p>Note that each builder class covariantly returns the appropriate type
    342      * of {@code ImmutableCollection} from this method.
    343      */
    344     public abstract ImmutableCollection<E> build();
    345   }
    346 }
    347