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 }