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 17package com.google.common.collect; 18 19import com.google.common.annotations.GwtCompatible; 20 21import java.io.Serializable; 22import java.util.Collection; 23import java.util.Iterator; 24 25import javax.annotation.Nullable; 26 27/** 28 * An immutable collection. Does not permit null elements. 29 * 30 * <p>In addition to the {@link Collection} methods, this class has an {@link 31 * #asList()} method, which returns a list view of the collection's elements. 32 * 33 * <p><b>Note:</b> Although this class is not final, it cannot be subclassed 34 * outside of this package as it has no public or protected constructors. Thus, 35 * instances of this type are guaranteed to be immutable. 36 * 37 * @author Jesse Wilson 38 * @since 2.0 (imported from Google Collections Library) 39 */ 40@GwtCompatible(emulated = true) 41@SuppressWarnings("serial") // we're overriding default serialization 42public abstract class ImmutableCollection<E> 43 implements Collection<E>, Serializable { 44 static final ImmutableCollection<Object> EMPTY_IMMUTABLE_COLLECTION 45 = new EmptyImmutableCollection(); 46 47 ImmutableCollection() {} 48 49 /** 50 * Returns an unmodifiable iterator across the elements in this collection. 51 */ 52 @Override 53 public abstract UnmodifiableIterator<E> iterator(); 54 55 @Override 56 public Object[] toArray() { 57 return ObjectArrays.toArrayImpl(this); 58 } 59 60 @Override 61 public <T> T[] toArray(T[] other) { 62 return ObjectArrays.toArrayImpl(this, other); 63 } 64 65 @Override 66 public boolean contains(@Nullable Object object) { 67 return object != null && Iterators.contains(iterator(), object); 68 } 69 70 @Override 71 public boolean containsAll(Collection<?> targets) { 72 return Collections2.containsAllImpl(this, targets); 73 } 74 75 @Override 76 public boolean isEmpty() { 77 return size() == 0; 78 } 79 80 @Override public String toString() { 81 return Collections2.toStringImpl(this); 82 } 83 84 /** 85 * Guaranteed to throw an exception and leave the collection unmodified. 86 * 87 * @throws UnsupportedOperationException always 88 */ 89 @Override 90 public final boolean add(E e) { 91 throw new UnsupportedOperationException(); 92 } 93 94 /** 95 * Guaranteed to throw an exception and leave the collection unmodified. 96 * 97 * @throws UnsupportedOperationException always 98 */ 99 @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.0 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 * @since 10.0 273 */ 274 public abstract static class Builder<E> { 275 276 Builder() { 277 } 278 279 /** 280 * Adds {@code element} to the {@code ImmutableCollection} being built. 281 * 282 * <p>Note that each builder class covariantly returns its own type from 283 * this method. 284 * 285 * @param element the element to add 286 * @return this {@code Builder} instance 287 * @throws NullPointerException if {@code element} is null 288 */ 289 public abstract Builder<E> add(E element); 290 291 /** 292 * Adds each element of {@code elements} to the {@code ImmutableCollection} 293 * being built. 294 * 295 * <p>Note that each builder class overrides this method in order to 296 * covariantly return its own type. 297 * 298 * @param elements the elements to add 299 * @return this {@code Builder} instance 300 * @throws NullPointerException if {@code elements} is null or contains a 301 * null element 302 */ 303 public Builder<E> add(E... elements) { 304 for (E element : elements) { 305 add(element); 306 } 307 return this; 308 } 309 310 /** 311 * Adds each element of {@code elements} to the {@code ImmutableCollection} 312 * being built. 313 * 314 * <p>Note that each builder class overrides this method in order to 315 * covariantly return its own type. 316 * 317 * @param elements the elements to add 318 * @return this {@code Builder} instance 319 * @throws NullPointerException if {@code elements} is null or contains a 320 * null element 321 */ 322 public Builder<E> addAll(Iterable<? extends E> elements) { 323 for (E element : elements) { 324 add(element); 325 } 326 return this; 327 } 328 329 /** 330 * Adds each element of {@code elements} to the {@code ImmutableCollection} 331 * being built. 332 * 333 * <p>Note that each builder class overrides this method in order to 334 * covariantly return its own type. 335 * 336 * @param elements the elements to add 337 * @return this {@code Builder} instance 338 * @throws NullPointerException if {@code elements} is null or contains a 339 * null element 340 */ 341 public Builder<E> addAll(Iterator<? extends E> elements) { 342 while (elements.hasNext()) { 343 add(elements.next()); 344 } 345 return this; 346 } 347 348 /** 349 * Returns a newly-created {@code ImmutableCollection} of the appropriate 350 * type, containing the elements provided to this builder. 351 * 352 * <p>Note that each builder class covariantly returns the appropriate type 353 * of {@code ImmutableCollection} from this method. 354 */ 355 public abstract ImmutableCollection<E> build(); 356 } 357} 358