001/* 002 * Copyright (C) 2007 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.collect.ObjectArrays.checkElementNotNull; 021 022import com.google.common.annotations.GwtCompatible; 023import com.google.common.annotations.VisibleForTesting; 024import com.google.common.primitives.Ints; 025import com.google.errorprone.annotations.CanIgnoreReturnValue; 026import com.google.errorprone.annotations.concurrent.LazyInit; 027import java.io.Serializable; 028import java.util.Arrays; 029import java.util.Collection; 030import java.util.Collections; 031import java.util.EnumSet; 032import java.util.Iterator; 033import java.util.Set; 034import javax.annotation.Nullable; 035 036/** 037 * A {@link Set} whose contents will never change, with many other important properties detailed at 038 * {@link ImmutableCollection}. 039 * 040 * @since 2.0 041 */ 042@GwtCompatible(serializable = true, emulated = true) 043@SuppressWarnings("serial") // we're overriding default serialization 044public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements Set<E> { 045 /** 046 * Returns the empty immutable set. Preferred over {@link Collections#emptySet} for code 047 * consistency, and because the return type conveys the immutability guarantee. 048 */ 049 @SuppressWarnings({"unchecked"}) // fully variant implementation (never actually produces any Es) 050 public static <E> ImmutableSet<E> of() { 051 return (ImmutableSet<E>) RegularImmutableSet.EMPTY; 052 } 053 054 /** 055 * Returns an immutable set containing {@code element}. Preferred over {@link 056 * Collections#singleton} for code consistency, {@code null} rejection, and because the return 057 * type conveys the immutability guarantee. 058 */ 059 public static <E> ImmutableSet<E> of(E element) { 060 return new SingletonImmutableSet<E>(element); 061 } 062 063 /** 064 * Returns an immutable set containing the given elements, minus duplicates, in the order each was 065 * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except 066 * the first are ignored. 067 */ 068 public static <E> ImmutableSet<E> of(E e1, E e2) { 069 return construct(2, e1, e2); 070 } 071 072 /** 073 * Returns an immutable set containing the given elements, minus duplicates, in the order each was 074 * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except 075 * the first are ignored. 076 */ 077 public static <E> ImmutableSet<E> of(E e1, E e2, E e3) { 078 return construct(3, e1, e2, e3); 079 } 080 081 /** 082 * Returns an immutable set containing the given elements, minus duplicates, in the order each was 083 * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except 084 * the first are ignored. 085 */ 086 public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4) { 087 return construct(4, e1, e2, e3, e4); 088 } 089 090 /** 091 * Returns an immutable set containing the given elements, minus duplicates, in the order each was 092 * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except 093 * the first are ignored. 094 */ 095 public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5) { 096 return construct(5, e1, e2, e3, e4, e5); 097 } 098 099 /** 100 * Returns an immutable set containing the given elements, minus duplicates, in the order each was 101 * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except 102 * the first are ignored. 103 * 104 * @since 3.0 (source-compatible since 2.0) 105 */ 106 @SafeVarargs // For Eclipse. For internal javac we have disabled this pointless type of warning. 107 public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) { 108 final int paramCount = 6; 109 Object[] elements = new Object[paramCount + others.length]; 110 elements[0] = e1; 111 elements[1] = e2; 112 elements[2] = e3; 113 elements[3] = e4; 114 elements[4] = e5; 115 elements[5] = e6; 116 System.arraycopy(others, 0, elements, paramCount, others.length); 117 return construct(elements.length, elements); 118 } 119 120 /** 121 * Constructs an {@code ImmutableSet} from the first {@code n} elements of the specified array. 122 * If {@code k} is the size of the returned {@code ImmutableSet}, then the unique elements of 123 * {@code elements} will be in the first {@code k} positions, and {@code elements[i] == null} for 124 * {@code k <= i < n}. 125 * 126 * <p>This may modify {@code elements}. Additionally, if {@code n == elements.length} and 127 * {@code elements} contains no duplicates, {@code elements} may be used without copying in the 128 * returned {@code ImmutableSet}, in which case it may no longer be modified. 129 * 130 * <p>{@code elements} may contain only values of type {@code E}. 131 * 132 * @throws NullPointerException if any of the first {@code n} elements of {@code elements} is 133 * null 134 */ 135 private static <E> ImmutableSet<E> construct(int n, Object... elements) { 136 switch (n) { 137 case 0: 138 return of(); 139 case 1: 140 @SuppressWarnings("unchecked") // safe; elements contains only E's 141 E elem = (E) elements[0]; 142 return of(elem); 143 default: 144 // continue below to handle the general case 145 } 146 int tableSize = chooseTableSize(n); 147 Object[] table = new Object[tableSize]; 148 int mask = tableSize - 1; 149 int hashCode = 0; 150 int uniques = 0; 151 for (int i = 0; i < n; i++) { 152 Object element = checkElementNotNull(elements[i], i); 153 int hash = element.hashCode(); 154 for (int j = Hashing.smear(hash); ; j++) { 155 int index = j & mask; 156 Object value = table[index]; 157 if (value == null) { 158 // Came to an empty slot. Put the element here. 159 elements[uniques++] = element; 160 table[index] = element; 161 hashCode += hash; 162 break; 163 } else if (value.equals(element)) { 164 break; 165 } 166 } 167 } 168 Arrays.fill(elements, uniques, n, null); 169 if (uniques == 1) { 170 // There is only one element or elements are all duplicates 171 @SuppressWarnings("unchecked") // we are careful to only pass in E 172 E element = (E) elements[0]; 173 return new SingletonImmutableSet<E>(element, hashCode); 174 } else if (tableSize != chooseTableSize(uniques)) { 175 // Resize the table when the array includes too many duplicates. 176 // when this happens, we have already made a copy 177 return construct(uniques, elements); 178 } else { 179 Object[] uniqueElements = 180 (uniques < elements.length) ? ObjectArrays.arraysCopyOf(elements, uniques) : elements; 181 return new RegularImmutableSet<E>(uniqueElements, hashCode, table, mask); 182 } 183 } 184 185 // We use power-of-2 tables, and this is the highest int that's a power of 2 186 static final int MAX_TABLE_SIZE = Ints.MAX_POWER_OF_TWO; 187 188 // Represents how tightly we can pack things, as a maximum. 189 private static final double DESIRED_LOAD_FACTOR = 0.7; 190 191 // If the set has this many elements, it will "max out" the table size 192 private static final int CUTOFF = (int) (MAX_TABLE_SIZE * DESIRED_LOAD_FACTOR); 193 194 /** 195 * Returns an array size suitable for the backing array of a hash table that 196 * uses open addressing with linear probing in its implementation. The 197 * returned size is the smallest power of two that can hold setSize elements 198 * with the desired load factor. 199 * 200 * <p>Do not call this method with setSize < 2. 201 */ 202 @VisibleForTesting 203 static int chooseTableSize(int setSize) { 204 // Correct the size for open addressing to match desired load factor. 205 if (setSize < CUTOFF) { 206 // Round up to the next highest power of 2. 207 int tableSize = Integer.highestOneBit(setSize - 1) << 1; 208 while (tableSize * DESIRED_LOAD_FACTOR < setSize) { 209 tableSize <<= 1; 210 } 211 return tableSize; 212 } 213 214 // The table can't be completely full or we'll get infinite reprobes 215 checkArgument(setSize < MAX_TABLE_SIZE, "collection too large"); 216 return MAX_TABLE_SIZE; 217 } 218 219 /** 220 * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order 221 * each appears first in the source collection. 222 * 223 * <p><b>Performance note:</b> This method will sometimes recognize that the actual copy operation 224 * is unnecessary; for example, {@code copyOf(copyOf(anArrayList))} will copy the data only once. 225 * This reduces the expense of habitually making defensive copies at API boundaries. However, the 226 * precise conditions for skipping the copy operation are undefined. 227 * 228 * @throws NullPointerException if any of {@code elements} is null 229 * @since 7.0 (source-compatible since 2.0) 230 */ 231 public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) { 232 /* 233 * TODO(lowasser): consider checking for ImmutableAsList here 234 * TODO(lowasser): consider checking for Multiset here 235 */ 236 if (elements instanceof ImmutableSet && !(elements instanceof ImmutableSortedSet)) { 237 @SuppressWarnings("unchecked") // all supported methods are covariant 238 ImmutableSet<E> set = (ImmutableSet<E>) elements; 239 if (!set.isPartialView()) { 240 return set; 241 } 242 } else if (elements instanceof EnumSet) { 243 return copyOfEnumSet((EnumSet) elements); 244 } 245 Object[] array = elements.toArray(); 246 return construct(array.length, array); 247 } 248 249 /** 250 * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order 251 * each appears first in the source iterable. This method iterates over {@code elements} only 252 * once. 253 * 254 * <p><b>Performance note:</b> This method will sometimes recognize that the actual copy operation 255 * is unnecessary; for example, {@code copyOf(copyOf(anArrayList))} should copy the data only 256 * once. This reduces the expense of habitually making defensive copies at API boundaries. 257 * However, the precise conditions for skipping the copy operation are undefined. 258 * 259 * @throws NullPointerException if any of {@code elements} is null 260 */ 261 public static <E> ImmutableSet<E> copyOf(Iterable<? extends E> elements) { 262 return (elements instanceof Collection) 263 ? copyOf((Collection<? extends E>) elements) 264 : copyOf(elements.iterator()); 265 } 266 267 /** 268 * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order 269 * each appears first in the source iterator. 270 * 271 * @throws NullPointerException if any of {@code elements} is null 272 */ 273 public static <E> ImmutableSet<E> copyOf(Iterator<? extends E> elements) { 274 // We special-case for 0 or 1 elements, but anything further is madness. 275 if (!elements.hasNext()) { 276 return of(); 277 } 278 E first = elements.next(); 279 if (!elements.hasNext()) { 280 return of(first); 281 } else { 282 return new ImmutableSet.Builder<E>().add(first).addAll(elements).build(); 283 } 284 } 285 286 /** 287 * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order 288 * each appears first in the source array. 289 * 290 * @throws NullPointerException if any of {@code elements} is null 291 * @since 3.0 292 */ 293 public static <E> ImmutableSet<E> copyOf(E[] elements) { 294 switch (elements.length) { 295 case 0: 296 return of(); 297 case 1: 298 return of(elements[0]); 299 default: 300 return construct(elements.length, elements.clone()); 301 } 302 } 303 304 @SuppressWarnings("rawtypes") // necessary to compile against Java 8 305 private static ImmutableSet copyOfEnumSet(EnumSet enumSet) { 306 return ImmutableEnumSet.asImmutable(EnumSet.copyOf(enumSet)); 307 } 308 309 ImmutableSet() {} 310 311 /** Returns {@code true} if the {@code hashCode()} method runs quickly. */ 312 boolean isHashCodeFast() { 313 return false; 314 } 315 316 @Override 317 public boolean equals(@Nullable Object object) { 318 if (object == this) { 319 return true; 320 } else if (object instanceof ImmutableSet 321 && isHashCodeFast() 322 && ((ImmutableSet<?>) object).isHashCodeFast() 323 && hashCode() != object.hashCode()) { 324 return false; 325 } 326 return Sets.equalsImpl(this, object); 327 } 328 329 @Override 330 public int hashCode() { 331 return Sets.hashCodeImpl(this); 332 } 333 334 // This declaration is needed to make Set.iterator() and 335 // ImmutableCollection.iterator() consistent. 336 @Override 337 public abstract UnmodifiableIterator<E> iterator(); 338 339 @LazyInit 340 private transient ImmutableList<E> asList; 341 342 @Override 343 public ImmutableList<E> asList() { 344 ImmutableList<E> result = asList; 345 return (result == null) ? asList = createAsList() : result; 346 } 347 348 ImmutableList<E> createAsList() { 349 return new RegularImmutableAsList<E>(this, toArray()); 350 } 351 352 abstract static class Indexed<E> extends ImmutableSet<E> { 353 abstract E get(int index); 354 355 @Override 356 public UnmodifiableIterator<E> iterator() { 357 return asList().iterator(); 358 } 359 360 @Override 361 ImmutableList<E> createAsList() { 362 return new ImmutableAsList<E>() { 363 @Override 364 public E get(int index) { 365 return Indexed.this.get(index); 366 } 367 368 @Override 369 Indexed<E> delegateCollection() { 370 return Indexed.this; 371 } 372 }; 373 } 374 } 375 376 /* 377 * This class is used to serialize all ImmutableSet instances, except for 378 * ImmutableEnumSet/ImmutableSortedSet, regardless of implementation type. It 379 * captures their "logical contents" and they are reconstructed using public 380 * static factories. This is necessary to ensure that the existence of a 381 * particular implementation type is an implementation detail. 382 */ 383 private static class SerializedForm implements Serializable { 384 final Object[] elements; 385 386 SerializedForm(Object[] elements) { 387 this.elements = elements; 388 } 389 390 Object readResolve() { 391 return copyOf(elements); 392 } 393 394 private static final long serialVersionUID = 0; 395 } 396 397 @Override 398 Object writeReplace() { 399 return new SerializedForm(toArray()); 400 } 401 402 /** 403 * Returns a new builder. The generated builder is equivalent to the builder 404 * created by the {@link Builder} constructor. 405 */ 406 public static <E> Builder<E> builder() { 407 return new Builder<E>(); 408 } 409 410 /** 411 * A builder for creating {@code ImmutableSet} instances. Example: <pre> {@code 412 * 413 * static final ImmutableSet<Color> GOOGLE_COLORS = 414 * ImmutableSet.<Color>builder() 415 * .addAll(WEBSAFE_COLORS) 416 * .add(new Color(0, 191, 255)) 417 * .build();}</pre> 418 * 419 * <p>Building does not change the state of the builder, so it is still possible to add more 420 * elements and to build again. 421 * 422 * @since 2.0 423 */ 424 public static class Builder<E> extends ImmutableCollection.ArrayBasedBuilder<E> { 425 426 /** 427 * Creates a new builder. The returned builder is equivalent to the builder 428 * generated by {@link ImmutableSet#builder}. 429 */ 430 public Builder() { 431 this(DEFAULT_INITIAL_CAPACITY); 432 } 433 434 Builder(int capacity) { 435 super(capacity); 436 } 437 438 /** 439 * Adds {@code element} to the {@code ImmutableSet}. If the {@code 440 * ImmutableSet} already contains {@code element}, then {@code add} has no 441 * effect (only the previously added element is retained). 442 * 443 * @param element the element to add 444 * @return this {@code Builder} object 445 * @throws NullPointerException if {@code element} is null 446 */ 447 @CanIgnoreReturnValue 448 @Override 449 public Builder<E> add(E element) { 450 super.add(element); 451 return this; 452 } 453 454 /** 455 * Adds each element of {@code elements} to the {@code ImmutableSet}, 456 * ignoring duplicate elements (only the first duplicate element is added). 457 * 458 * @param elements the elements to add 459 * @return this {@code Builder} object 460 * @throws NullPointerException if {@code elements} is null or contains a 461 * null element 462 */ 463 @CanIgnoreReturnValue 464 @Override 465 public Builder<E> add(E... elements) { 466 super.add(elements); 467 return this; 468 } 469 470 /** 471 * Adds each element of {@code elements} to the {@code ImmutableSet}, 472 * ignoring duplicate elements (only the first duplicate element is added). 473 * 474 * @param elements the {@code Iterable} to add to the {@code ImmutableSet} 475 * @return this {@code Builder} object 476 * @throws NullPointerException if {@code elements} is null or contains a 477 * null element 478 */ 479 @CanIgnoreReturnValue 480 @Override 481 public Builder<E> addAll(Iterable<? extends E> elements) { 482 super.addAll(elements); 483 return this; 484 } 485 486 /** 487 * Adds each element of {@code elements} to the {@code ImmutableSet}, 488 * ignoring duplicate elements (only the first duplicate element is added). 489 * 490 * @param elements the elements to add to the {@code ImmutableSet} 491 * @return this {@code Builder} object 492 * @throws NullPointerException if {@code elements} is null or contains a 493 * null element 494 */ 495 @CanIgnoreReturnValue 496 @Override 497 public Builder<E> addAll(Iterator<? extends E> elements) { 498 super.addAll(elements); 499 return this; 500 } 501 502 /** 503 * Returns a newly-created {@code ImmutableSet} based on the contents of 504 * the {@code Builder}. 505 */ 506 @Override 507 public ImmutableSet<E> build() { 508 ImmutableSet<E> result = construct(size, contents); 509 // construct has the side effect of deduping contents, so we update size 510 // accordingly. 511 size = result.size(); 512 return result; 513 } 514 } 515}