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