001 /* 002 * Copyright (C) 2008 Google Inc. 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 public abstract UnmodifiableIterator<E> iterator(); 053 054 public Object[] toArray() { 055 return ObjectArrays.toArrayImpl(this); 056 } 057 058 public <T> T[] toArray(T[] other) { 059 return ObjectArrays.toArrayImpl(this, other); 060 } 061 062 public boolean contains(@Nullable Object object) { 063 return object != null && Iterators.contains(iterator(), object); 064 } 065 066 public boolean containsAll(Collection<?> targets) { 067 return Collections2.containsAllImpl(this, targets); 068 } 069 070 public boolean isEmpty() { 071 return size() == 0; 072 } 073 074 @Override public String toString() { 075 return Collections2.toStringImpl(this); 076 } 077 078 /** 079 * Guaranteed to throw an exception and leave the collection unmodified. 080 * 081 * @throws UnsupportedOperationException always 082 */ 083 public final boolean add(E e) { 084 throw new UnsupportedOperationException(); 085 } 086 087 /** 088 * Guaranteed to throw an exception and leave the collection unmodified. 089 * 090 * @throws UnsupportedOperationException always 091 */ 092 public final boolean remove(Object object) { 093 throw new UnsupportedOperationException(); 094 } 095 096 /** 097 * Guaranteed to throw an exception and leave the collection unmodified. 098 * 099 * @throws UnsupportedOperationException always 100 */ 101 public final boolean addAll(Collection<? extends E> newElements) { 102 throw new UnsupportedOperationException(); 103 } 104 105 /** 106 * Guaranteed to throw an exception and leave the collection unmodified. 107 * 108 * @throws UnsupportedOperationException always 109 */ 110 public final boolean removeAll(Collection<?> oldElements) { 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 public final boolean retainAll(Collection<?> elementsToKeep) { 120 throw new UnsupportedOperationException(); 121 } 122 123 /** 124 * Guaranteed to throw an exception and leave the collection unmodified. 125 * 126 * @throws UnsupportedOperationException always 127 */ 128 public final void clear() { 129 throw new UnsupportedOperationException(); 130 } 131 132 /* 133 * TODO(kevinb): Restructure code so ImmutableList doesn't contain this 134 * variable, which it doesn't use. 135 */ 136 private transient ImmutableList<E> asList; 137 138 /** 139 * Returns a list view of the collection. 140 * 141 * @since 2 142 */ 143 public ImmutableList<E> asList() { 144 ImmutableList<E> list = asList; 145 return (list == null) ? (asList = createAsList()) : list; 146 } 147 148 ImmutableList<E> createAsList() { 149 switch (size()) { 150 case 0: 151 return ImmutableList.of(); 152 case 1: 153 return ImmutableList.of(iterator().next()); 154 default: 155 return new ImmutableAsList<E>(toArray(), this); 156 } 157 } 158 159 abstract boolean isPartialView(); 160 161 private static class EmptyImmutableCollection 162 extends ImmutableCollection<Object> { 163 public int size() { 164 return 0; 165 } 166 167 @Override public boolean isEmpty() { 168 return true; 169 } 170 171 @Override public boolean contains(@Nullable Object object) { 172 return false; 173 } 174 175 @Override public UnmodifiableIterator<Object> iterator() { 176 return Iterators.EMPTY_ITERATOR; 177 } 178 179 private static final Object[] EMPTY_ARRAY = new Object[0]; 180 181 @Override public Object[] toArray() { 182 return EMPTY_ARRAY; 183 } 184 185 @Override public <T> T[] toArray(T[] array) { 186 if (array.length > 0) { 187 array[0] = null; 188 } 189 return array; 190 } 191 192 @Override ImmutableList<Object> createAsList() { 193 return ImmutableList.of(); 194 } 195 196 @Override boolean isPartialView() { 197 return false; 198 } 199 } 200 201 /** 202 * Nonempty collection stored in an array. 203 */ 204 private static class ArrayImmutableCollection<E> 205 extends ImmutableCollection<E> { 206 private final E[] elements; 207 208 ArrayImmutableCollection(E[] elements) { 209 this.elements = elements; 210 } 211 212 public int size() { 213 return elements.length; 214 } 215 216 @Override public boolean isEmpty() { 217 return false; 218 } 219 220 @Override public UnmodifiableIterator<E> iterator() { 221 return Iterators.forArray(elements); 222 } 223 224 @Override ImmutableList<E> createAsList() { 225 return elements.length == 1 ? new SingletonImmutableList<E>(elements[0]) 226 : new RegularImmutableList<E>(elements); 227 } 228 229 @Override boolean isPartialView() { 230 return false; 231 } 232 } 233 234 /* 235 * Serializes ImmutableCollections as their logical contents. This ensures 236 * that implementation types do not leak into the serialized representation. 237 */ 238 private static class SerializedForm implements Serializable { 239 final Object[] elements; 240 SerializedForm(Object[] elements) { 241 this.elements = elements; 242 } 243 Object readResolve() { 244 return elements.length == 0 245 ? EMPTY_IMMUTABLE_COLLECTION 246 : new ArrayImmutableCollection<Object>(Platform.clone(elements)); 247 } 248 private static final long serialVersionUID = 0; 249 } 250 251 Object writeReplace() { 252 return new SerializedForm(toArray()); 253 } 254 255 /** 256 * Abstract base class for builders of {@link ImmutableCollection} types. 257 */ 258 abstract static class Builder<E> { 259 /** 260 * Adds {@code element} to the {@code ImmutableCollection} being built. 261 * 262 * <p>Note that each builder class covariantly returns its own type from 263 * this method. 264 * 265 * @param element the element to add 266 * @return this {@code Builder} instance 267 * @throws NullPointerException if {@code element} is null 268 */ 269 public abstract Builder<E> add(E element); 270 271 /** 272 * Adds each element of {@code elements} to the {@code ImmutableCollection} 273 * being built. 274 * 275 * <p>Note that each builder class overrides this method in order to 276 * covariantly return its own type. 277 * 278 * @param elements the elements to add 279 * @return this {@code Builder} instance 280 * @throws NullPointerException if {@code elements} is null or contains a 281 * null element 282 */ 283 public Builder<E> add(E... elements) { 284 for (E element : elements) { 285 add(element); 286 } 287 return this; 288 } 289 290 /** 291 * Adds each element of {@code elements} to the {@code ImmutableCollection} 292 * being built. 293 * 294 * <p>Note that each builder class overrides this method in order to 295 * covariantly return its own type. 296 * 297 * @param elements the elements to add 298 * @return this {@code Builder} instance 299 * @throws NullPointerException if {@code elements} is null or contains a 300 * null element 301 */ 302 public Builder<E> addAll(Iterable<? extends E> elements) { 303 for (E element : elements) { 304 add(element); 305 } 306 return this; 307 } 308 309 /** 310 * Adds each element of {@code elements} to the {@code ImmutableCollection} 311 * being built. 312 * 313 * <p>Note that each builder class overrides this method in order to 314 * covariantly return its own type. 315 * 316 * @param elements the elements to add 317 * @return this {@code Builder} instance 318 * @throws NullPointerException if {@code elements} is null or contains a 319 * null element 320 */ 321 public Builder<E> addAll(Iterator<? extends E> elements) { 322 while (elements.hasNext()) { 323 add(elements.next()); 324 } 325 return this; 326 } 327 328 /** 329 * Returns a newly-created {@code ImmutableCollection} of the appropriate 330 * type, containing the elements provided to this builder. 331 * 332 * <p>Note that each builder class covariantly returns the appropriate type 333 * of {@code ImmutableCollection} from this method. 334 */ 335 public abstract ImmutableCollection<E> build(); 336 } 337 }