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 static com.google.common.base.Preconditions.checkArgument; 020import static com.google.common.base.Preconditions.checkNotNull; 021import static com.google.common.collect.ObjectArrays.checkElementsNotNull; 022 023import com.google.common.annotations.GwtCompatible; 024 025import java.io.Serializable; 026import java.util.AbstractCollection; 027import java.util.Collection; 028import java.util.Iterator; 029 030import javax.annotation.Nullable; 031 032/** 033 * An immutable collection. Does not permit null elements. 034 * 035 * <p>In addition to the {@link Collection} methods, this class has an {@link 036 * #asList()} method, which returns a list view of the collection's elements. 037 * 038 * <p><b>Note:</b> Although this class is not final, it cannot be subclassed 039 * outside of this package as it has no public or protected constructors. Thus, 040 * instances of this type are guaranteed to be immutable. 041 * 042 * @author Jesse Wilson 043 * @since 2.0 (imported from Google Collections Library) 044 */ 045@GwtCompatible(emulated = true) 046@SuppressWarnings("serial") // we're overriding default serialization 047public abstract class ImmutableCollection<E> extends AbstractCollection<E> 048 implements Serializable { 049 050 ImmutableCollection() {} 051 052 /** 053 * Returns an unmodifiable iterator across the elements in this collection. 054 */ 055 @Override 056 public abstract UnmodifiableIterator<E> iterator(); 057 058 @Override 059 public final Object[] toArray() { 060 int size = size(); 061 if (size == 0) { 062 return ObjectArrays.EMPTY_ARRAY; 063 } 064 Object[] result = new Object[size()]; 065 copyIntoArray(result, 0); 066 return result; 067 } 068 069 @Override 070 public final <T> T[] toArray(T[] other) { 071 checkNotNull(other); 072 int size = size(); 073 if (other.length < size) { 074 other = ObjectArrays.newArray(other, size); 075 } else if (other.length > size) { 076 other[size] = null; 077 } 078 copyIntoArray(other, 0); 079 return other; 080 } 081 082 @Override 083 public boolean contains(@Nullable Object object) { 084 return object != null && super.contains(object); 085 } 086 087 /** 088 * Guaranteed to throw an exception and leave the collection unmodified. 089 * 090 * @throws UnsupportedOperationException always 091 * @deprecated Unsupported operation. 092 */ 093 @Deprecated 094 @Override 095 public final boolean add(E e) { 096 throw new UnsupportedOperationException(); 097 } 098 099 /** 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 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 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 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 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 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 */ 170 public ImmutableList<E> asList() { 171 ImmutableList<E> list = asList; 172 return (list == null) ? (asList = createAsList()) : list; 173 } 174 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 */ 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 */ 198 int copyIntoArray(Object[] dst, int offset) { 199 for (E e : this) { 200 dst[offset++] = e; 201 } 202 return offset; 203 } 204 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 320 ArrayBasedBuilder(int initialCapacity) { 321 checkArgument(initialCapacity >= 0, "capacity must be >= 0 but was %s", 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 */ 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 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 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 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}