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