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