001 /*
002 * Copyright (C) 2008 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
017 package com.google.common.collect;
018
019 import com.google.common.annotations.GwtCompatible;
020
021 import java.io.Serializable;
022 import java.util.Collection;
023 import java.util.Iterator;
024
025 import javax.annotation.Nullable;
026
027 /**
028 * An immutable collection. Does not permit null elements.
029 *
030 * <p>In addition to the {@link Collection} methods, this class has an {@link
031 * #asList()} method, which returns a list view of the collection's elements.
032 *
033 * <p><b>Note</b>: Although this class is not final, it cannot be subclassed
034 * outside of this package as it has no public or protected constructors. Thus,
035 * instances of this type are guaranteed to be immutable.
036 *
037 * @author Jesse Wilson
038 * @since 2 (imported from Google Collections Library)
039 */
040 @GwtCompatible(emulated = true)
041 @SuppressWarnings("serial") // we're overriding default serialization
042 public abstract class ImmutableCollection<E>
043 implements Collection<E>, Serializable {
044 static final ImmutableCollection<Object> EMPTY_IMMUTABLE_COLLECTION
045 = new EmptyImmutableCollection();
046
047 ImmutableCollection() {}
048
049 /**
050 * Returns an unmodifiable iterator across the elements in this collection.
051 */
052 @Override
053 public abstract UnmodifiableIterator<E> iterator();
054
055 @Override
056 public Object[] toArray() {
057 return ObjectArrays.toArrayImpl(this);
058 }
059
060 @Override
061 public <T> T[] toArray(T[] other) {
062 return ObjectArrays.toArrayImpl(this, other);
063 }
064
065 @Override
066 public boolean contains(@Nullable Object object) {
067 return object != null && Iterators.contains(iterator(), object);
068 }
069
070 @Override
071 public boolean containsAll(Collection<?> targets) {
072 return Collections2.containsAllImpl(this, targets);
073 }
074
075 @Override
076 public boolean isEmpty() {
077 return size() == 0;
078 }
079
080 @Override public String toString() {
081 return Collections2.toStringImpl(this);
082 }
083
084 /**
085 * Guaranteed to throw an exception and leave the collection unmodified.
086 *
087 * @throws UnsupportedOperationException always
088 */
089 @Override
090 public final boolean add(E e) {
091 throw new UnsupportedOperationException();
092 }
093
094 /**
095 * Guaranteed to throw an exception and leave the collection unmodified.
096 *
097 * @throws UnsupportedOperationException always
098 */
099 @Override
100 public final boolean remove(Object object) {
101 throw new UnsupportedOperationException();
102 }
103
104 /**
105 * Guaranteed to throw an exception and leave the collection unmodified.
106 *
107 * @throws UnsupportedOperationException always
108 */
109 @Override
110 public final boolean addAll(Collection<? extends E> newElements) {
111 throw new UnsupportedOperationException();
112 }
113
114 /**
115 * Guaranteed to throw an exception and leave the collection unmodified.
116 *
117 * @throws UnsupportedOperationException always
118 */
119 @Override
120 public final boolean removeAll(Collection<?> oldElements) {
121 throw new UnsupportedOperationException();
122 }
123
124 /**
125 * Guaranteed to throw an exception and leave the collection unmodified.
126 *
127 * @throws UnsupportedOperationException always
128 */
129 @Override
130 public final boolean retainAll(Collection<?> elementsToKeep) {
131 throw new UnsupportedOperationException();
132 }
133
134 /**
135 * Guaranteed to throw an exception and leave the collection unmodified.
136 *
137 * @throws UnsupportedOperationException always
138 */
139 @Override
140 public final void clear() {
141 throw new UnsupportedOperationException();
142 }
143
144 /*
145 * TODO(kevinb): Restructure code so ImmutableList doesn't contain this
146 * variable, which it doesn't use.
147 */
148 private transient ImmutableList<E> asList;
149
150 /**
151 * Returns a list view of the collection.
152 *
153 * @since 2
154 */
155 public ImmutableList<E> asList() {
156 ImmutableList<E> list = asList;
157 return (list == null) ? (asList = createAsList()) : list;
158 }
159
160 ImmutableList<E> createAsList() {
161 switch (size()) {
162 case 0:
163 return ImmutableList.of();
164 case 1:
165 return ImmutableList.of(iterator().next());
166 default:
167 return new ImmutableAsList<E>(toArray(), this);
168 }
169 }
170
171 abstract boolean isPartialView();
172
173 private static class EmptyImmutableCollection
174 extends ImmutableCollection<Object> {
175 @Override
176 public int size() {
177 return 0;
178 }
179
180 @Override public boolean isEmpty() {
181 return true;
182 }
183
184 @Override public boolean contains(@Nullable Object object) {
185 return false;
186 }
187
188 @Override public UnmodifiableIterator<Object> iterator() {
189 return Iterators.EMPTY_ITERATOR;
190 }
191
192 private static final Object[] EMPTY_ARRAY = new Object[0];
193
194 @Override public Object[] toArray() {
195 return EMPTY_ARRAY;
196 }
197
198 @Override public <T> T[] toArray(T[] array) {
199 if (array.length > 0) {
200 array[0] = null;
201 }
202 return array;
203 }
204
205 @Override ImmutableList<Object> createAsList() {
206 return ImmutableList.of();
207 }
208
209 @Override boolean isPartialView() {
210 return false;
211 }
212 }
213
214 /**
215 * Nonempty collection stored in an array.
216 */
217 private static class ArrayImmutableCollection<E>
218 extends ImmutableCollection<E> {
219 private final E[] elements;
220
221 ArrayImmutableCollection(E[] elements) {
222 this.elements = elements;
223 }
224
225 @Override
226 public int size() {
227 return elements.length;
228 }
229
230 @Override public boolean isEmpty() {
231 return false;
232 }
233
234 @Override public UnmodifiableIterator<E> iterator() {
235 return Iterators.forArray(elements);
236 }
237
238 @Override ImmutableList<E> createAsList() {
239 return elements.length == 1 ? new SingletonImmutableList<E>(elements[0])
240 : new RegularImmutableList<E>(elements);
241 }
242
243 @Override boolean isPartialView() {
244 return false;
245 }
246 }
247
248 /*
249 * Serializes ImmutableCollections as their logical contents. This ensures
250 * that implementation types do not leak into the serialized representation.
251 */
252 private static class SerializedForm implements Serializable {
253 final Object[] elements;
254 SerializedForm(Object[] elements) {
255 this.elements = elements;
256 }
257 Object readResolve() {
258 return elements.length == 0
259 ? EMPTY_IMMUTABLE_COLLECTION
260 : new ArrayImmutableCollection<Object>(Platform.clone(elements));
261 }
262 private static final long serialVersionUID = 0;
263 }
264
265 Object writeReplace() {
266 return new SerializedForm(toArray());
267 }
268
269 /**
270 * Abstract base class for builders of {@link ImmutableCollection} types.
271 */
272 abstract static class Builder<E> {
273 /**
274 * Adds {@code element} to the {@code ImmutableCollection} being built.
275 *
276 * <p>Note that each builder class covariantly returns its own type from
277 * this method.
278 *
279 * @param element the element to add
280 * @return this {@code Builder} instance
281 * @throws NullPointerException if {@code element} is null
282 */
283 public abstract Builder<E> add(E element);
284
285 /**
286 * Adds each element of {@code elements} to the {@code ImmutableCollection}
287 * being built.
288 *
289 * <p>Note that each builder class overrides this method in order to
290 * covariantly return its own type.
291 *
292 * @param elements the elements to add
293 * @return this {@code Builder} instance
294 * @throws NullPointerException if {@code elements} is null or contains a
295 * null element
296 */
297 public Builder<E> add(E... elements) {
298 for (E element : elements) {
299 add(element);
300 }
301 return this;
302 }
303
304 /**
305 * Adds each element of {@code elements} to the {@code ImmutableCollection}
306 * being built.
307 *
308 * <p>Note that each builder class overrides this method in order to
309 * covariantly return its own type.
310 *
311 * @param elements the elements to add
312 * @return this {@code Builder} instance
313 * @throws NullPointerException if {@code elements} is null or contains a
314 * null element
315 */
316 public Builder<E> addAll(Iterable<? extends E> elements) {
317 for (E element : elements) {
318 add(element);
319 }
320 return this;
321 }
322
323 /**
324 * Adds each element of {@code elements} to the {@code ImmutableCollection}
325 * being built.
326 *
327 * <p>Note that each builder class overrides this method in order to
328 * covariantly return its own type.
329 *
330 * @param elements the elements to add
331 * @return this {@code Builder} instance
332 * @throws NullPointerException if {@code elements} is null or contains a
333 * null element
334 */
335 public Builder<E> addAll(Iterator<? extends E> elements) {
336 while (elements.hasNext()) {
337 add(elements.next());
338 }
339 return this;
340 }
341
342 /**
343 * Returns a newly-created {@code ImmutableCollection} of the appropriate
344 * type, containing the elements provided to this builder.
345 *
346 * <p>Note that each builder class covariantly returns the appropriate type
347 * of {@code ImmutableCollection} from this method.
348 */
349 public abstract ImmutableCollection<E> build();
350 }
351 }