• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 import static com.google.common.collect.CollectPreconditions.checkNonnegative;
21 import static com.google.common.collect.ObjectArrays.checkElementsNotNull;
22 
23 import com.google.common.annotations.GwtCompatible;
24 
25 import java.io.Serializable;
26 import java.util.AbstractCollection;
27 import java.util.Collection;
28 import java.util.Iterator;
29 
30 import javax.annotation.Nullable;
31 
32 /**
33  * An immutable collection. Does not permit null elements.
34  *
35  * <p>In addition to the {@link Collection} methods, this class has an {@link
36  * #asList()} method, which returns a list view of the collection's elements.
37  *
38  * <p><b>Note:</b> Although this class is not final, it cannot be subclassed
39  * outside of this package as it has no public or protected constructors. Thus,
40  * instances of this type are guaranteed to be immutable.
41  *
42  * @author Jesse Wilson
43  * @since 2.0 (imported from Google Collections Library)
44  */
45 @GwtCompatible(emulated = true)
46 @SuppressWarnings("serial") // we're overriding default serialization
47 public abstract class ImmutableCollection<E> extends AbstractCollection<E>
48     implements Serializable {
49 
ImmutableCollection()50   ImmutableCollection() {}
51 
52   /**
53    * Returns an unmodifiable iterator across the elements in this collection.
54    */
55   @Override
iterator()56   public abstract UnmodifiableIterator<E> iterator();
57 
58   @Override
toArray()59   public final Object[] toArray() {
60     int size = size();
61     if (size == 0) {
62       return ObjectArrays.EMPTY_ARRAY;
63     }
64     Object[] result = new Object[size];
65     copyIntoArray(result, 0);
66     return result;
67   }
68 
69   @Override
toArray(T[] other)70   public final <T> T[] toArray(T[] other) {
71     checkNotNull(other);
72     int size = size();
73     if (other.length < size) {
74       other = ObjectArrays.newArray(other, size);
75     } else if (other.length > size) {
76       other[size] = null;
77     }
78     copyIntoArray(other, 0);
79     return other;
80   }
81 
82   @Override
contains(@ullable Object object)83   public boolean contains(@Nullable Object object) {
84     return object != null && super.contains(object);
85   }
86 
87   /**
88    * Guaranteed to throw an exception and leave the collection unmodified.
89    *
90    * @throws UnsupportedOperationException always
91    * @deprecated Unsupported operation.
92    */
93   @Deprecated
94   @Override
add(E e)95   public final boolean add(E e) {
96     throw new UnsupportedOperationException();
97   }
98 
99   /**
100    * Guaranteed to throw an exception and leave the collection unmodified.
101    *
102    * @throws UnsupportedOperationException always
103    * @deprecated Unsupported operation.
104    */
105   @Deprecated
106   @Override
remove(Object object)107   public final boolean remove(Object object) {
108     throw new UnsupportedOperationException();
109   }
110 
111   /**
112    * Guaranteed to throw an exception and leave the collection unmodified.
113    *
114    * @throws UnsupportedOperationException always
115    * @deprecated Unsupported operation.
116    */
117   @Deprecated
118   @Override
addAll(Collection<? extends E> newElements)119   public final boolean addAll(Collection<? extends E> newElements) {
120     throw new UnsupportedOperationException();
121   }
122 
123   /**
124    * Guaranteed to throw an exception and leave the collection unmodified.
125    *
126    * @throws UnsupportedOperationException always
127    * @deprecated Unsupported operation.
128    */
129   @Deprecated
130   @Override
removeAll(Collection<?> oldElements)131   public final boolean removeAll(Collection<?> oldElements) {
132     throw new UnsupportedOperationException();
133   }
134 
135   /**
136    * Guaranteed to throw an exception and leave the collection unmodified.
137    *
138    * @throws UnsupportedOperationException always
139    * @deprecated Unsupported operation.
140    */
141   @Deprecated
142   @Override
retainAll(Collection<?> elementsToKeep)143   public final boolean retainAll(Collection<?> elementsToKeep) {
144     throw new UnsupportedOperationException();
145   }
146 
147   /**
148    * Guaranteed to throw an exception and leave the collection unmodified.
149    *
150    * @throws UnsupportedOperationException always
151    * @deprecated Unsupported operation.
152    */
153   @Deprecated
154   @Override
clear()155   public final void clear() {
156     throw new UnsupportedOperationException();
157   }
158 
159   /*
160    * TODO(kevinb): Restructure code so ImmutableList doesn't contain this
161    * variable, which it doesn't use.
162    */
163   private transient ImmutableList<E> asList;
164 
165   /**
166    * Returns a list view of the collection.
167    *
168    * @since 2.0
169    */
asList()170   public ImmutableList<E> asList() {
171     ImmutableList<E> list = asList;
172     return (list == null) ? (asList = createAsList()) : list;
173   }
174 
createAsList()175   ImmutableList<E> createAsList() {
176     switch (size()) {
177       case 0:
178         return ImmutableList.of();
179       case 1:
180         return ImmutableList.of(iterator().next());
181       default:
182         return new RegularImmutableAsList<E>(this, toArray());
183     }
184   }
185 
186   /**
187    * Returns {@code true} if this immutable collection's implementation contains references to
188    * user-created objects that aren't accessible via this collection's methods. This is generally
189    * used to determine whether {@code copyOf} implementations should make an explicit copy to avoid
190    * memory leaks.
191    */
isPartialView()192   abstract boolean isPartialView();
193 
194   /**
195    * Copies the contents of this immutable collection into the specified array at the specified
196    * offset.  Returns {@code offset + size()}.
197    */
copyIntoArray(Object[] dst, int offset)198   int copyIntoArray(Object[] dst, int offset) {
199     for (E e : this) {
200       dst[offset++] = e;
201     }
202     return offset;
203   }
204 
writeReplace()205   Object writeReplace() {
206     // We serialize by default to ImmutableList, the simplest thing that works.
207     return new ImmutableList.SerializedForm(toArray());
208   }
209 
210   /**
211    * Abstract base class for builders of {@link ImmutableCollection} types.
212    *
213    * @since 10.0
214    */
215   public abstract static class Builder<E> {
216     static final int DEFAULT_INITIAL_CAPACITY = 4;
217 
expandedCapacity(int oldCapacity, int minCapacity)218     static int expandedCapacity(int oldCapacity, int minCapacity) {
219       if (minCapacity < 0) {
220         throw new AssertionError("cannot store more than MAX_VALUE elements");
221       }
222       // careful of overflow!
223       int newCapacity = oldCapacity + (oldCapacity >> 1) + 1;
224       if (newCapacity < minCapacity) {
225         newCapacity = Integer.highestOneBit(minCapacity - 1) << 1;
226       }
227       if (newCapacity < 0) {
228         newCapacity = Integer.MAX_VALUE;
229         // guaranteed to be >= newCapacity
230       }
231       return newCapacity;
232     }
233 
Builder()234     Builder() {
235     }
236 
237     /**
238      * Adds {@code element} to the {@code ImmutableCollection} being built.
239      *
240      * <p>Note that each builder class covariantly returns its own type from
241      * this method.
242      *
243      * @param element the element to add
244      * @return this {@code Builder} instance
245      * @throws NullPointerException if {@code element} is null
246      */
add(E element)247     public abstract Builder<E> add(E element);
248 
249     /**
250      * Adds each element of {@code elements} to the {@code ImmutableCollection}
251      * being built.
252      *
253      * <p>Note that each builder class overrides this method in order to
254      * covariantly return its own type.
255      *
256      * @param elements the elements to add
257      * @return this {@code Builder} instance
258      * @throws NullPointerException if {@code elements} is null or contains a
259      *     null element
260      */
add(E... elements)261     public Builder<E> add(E... elements) {
262       for (E element : elements) {
263         add(element);
264       }
265       return this;
266     }
267 
268     /**
269      * Adds each element of {@code elements} to the {@code ImmutableCollection}
270      * being built.
271      *
272      * <p>Note that each builder class overrides this method in order to
273      * covariantly return its own type.
274      *
275      * @param elements the elements to add
276      * @return this {@code Builder} instance
277      * @throws NullPointerException if {@code elements} is null or contains a
278      *     null element
279      */
addAll(Iterable<? extends E> elements)280     public Builder<E> addAll(Iterable<? extends E> elements) {
281       for (E element : elements) {
282         add(element);
283       }
284       return this;
285     }
286 
287     /**
288      * Adds each element of {@code elements} to the {@code ImmutableCollection}
289      * being built.
290      *
291      * <p>Note that each builder class overrides this method in order to
292      * covariantly return its own type.
293      *
294      * @param elements the elements to add
295      * @return this {@code Builder} instance
296      * @throws NullPointerException if {@code elements} is null or contains a
297      *     null element
298      */
addAll(Iterator<? extends E> elements)299     public Builder<E> addAll(Iterator<? extends E> elements) {
300       while (elements.hasNext()) {
301         add(elements.next());
302       }
303       return this;
304     }
305 
306     /**
307      * Returns a newly-created {@code ImmutableCollection} of the appropriate
308      * type, containing the elements provided to this builder.
309      *
310      * <p>Note that each builder class covariantly returns the appropriate type
311      * of {@code ImmutableCollection} from this method.
312      */
build()313     public abstract ImmutableCollection<E> build();
314   }
315 
316   abstract static class ArrayBasedBuilder<E> extends ImmutableCollection.Builder<E> {
317     Object[] contents;
318     int size;
319 
ArrayBasedBuilder(int initialCapacity)320     ArrayBasedBuilder(int initialCapacity) {
321       checkNonnegative(initialCapacity, "initialCapacity");
322       this.contents = new Object[initialCapacity];
323       this.size = 0;
324     }
325 
326     /**
327      * Expand the absolute capacity of the builder so it can accept at least
328      * the specified number of elements without being resized.
329      */
ensureCapacity(int minCapacity)330     private void ensureCapacity(int minCapacity) {
331       if (contents.length < minCapacity) {
332         this.contents = ObjectArrays.arraysCopyOf(
333             this.contents, expandedCapacity(contents.length, minCapacity));
334       }
335     }
336 
337     @Override
add(E element)338     public ArrayBasedBuilder<E> add(E element) {
339       checkNotNull(element);
340       ensureCapacity(size + 1);
341       contents[size++] = element;
342       return this;
343     }
344 
345     @Override
add(E... elements)346     public Builder<E> add(E... elements) {
347       checkElementsNotNull(elements);
348       ensureCapacity(size + elements.length);
349       System.arraycopy(elements, 0, contents, size, elements.length);
350       size += elements.length;
351       return this;
352     }
353 
354     @Override
addAll(Iterable<? extends E> elements)355     public Builder<E> addAll(Iterable<? extends E> elements) {
356       if (elements instanceof Collection) {
357         Collection<?> collection = (Collection<?>) elements;
358         ensureCapacity(size + collection.size());
359       }
360       super.addAll(elements);
361       return this;
362     }
363   }
364 }
365