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.base.Preconditions.checkNotNull; 021import static com.google.common.collect.CollectPreconditions.checkNonnegative; 022import static java.util.Objects.requireNonNull; 023 024import com.google.common.annotations.GwtCompatible; 025import com.google.common.annotations.GwtIncompatible; 026import com.google.common.annotations.J2ktIncompatible; 027import com.google.common.annotations.VisibleForTesting; 028import com.google.common.math.IntMath; 029import com.google.common.primitives.Ints; 030import com.google.errorprone.annotations.CanIgnoreReturnValue; 031import com.google.errorprone.annotations.concurrent.LazyInit; 032import com.google.j2objc.annotations.RetainedWith; 033import java.io.InvalidObjectException; 034import java.io.ObjectInputStream; 035import java.io.Serializable; 036import java.math.RoundingMode; 037import java.util.Arrays; 038import java.util.Collection; 039import java.util.Collections; 040import java.util.EnumSet; 041import java.util.Iterator; 042import java.util.Set; 043import java.util.SortedSet; 044import java.util.Spliterator; 045import java.util.function.Consumer; 046import java.util.stream.Collector; 047import javax.annotation.CheckForNull; 048import org.checkerframework.checker.nullness.qual.Nullable; 049 050/** 051 * A {@link Set} whose contents will never change, with many other important properties detailed at 052 * {@link ImmutableCollection}. 053 * 054 * @since 2.0 055 */ 056@GwtCompatible(serializable = true, emulated = true) 057@SuppressWarnings("serial") // we're overriding default serialization 058@ElementTypesAreNonnullByDefault 059public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements Set<E> { 060 static final int SPLITERATOR_CHARACTERISTICS = 061 ImmutableCollection.SPLITERATOR_CHARACTERISTICS | Spliterator.DISTINCT; 062 063 /** 064 * Returns a {@code Collector} that accumulates the input elements into a new {@code 065 * ImmutableSet}. Elements appear in the resulting set in the encounter order of the stream; if 066 * the stream contains duplicates (according to {@link Object#equals(Object)}), only the first 067 * duplicate in encounter order will appear in the result. 068 * 069 * @since 21.0 070 */ 071 public static <E> Collector<E, ?, ImmutableSet<E>> toImmutableSet() { 072 return CollectCollectors.toImmutableSet(); 073 } 074 075 /** 076 * Returns the empty immutable set. Preferred over {@link Collections#emptySet} for code 077 * consistency, and because the return type conveys the immutability guarantee. 078 * 079 * <p><b>Performance note:</b> the instance returned is a singleton. 080 */ 081 @SuppressWarnings({"unchecked"}) // fully variant implementation (never actually produces any Es) 082 public static <E> ImmutableSet<E> of() { 083 return (ImmutableSet<E>) RegularImmutableSet.EMPTY; 084 } 085 086 /** 087 * Returns an immutable set containing {@code element}. Preferred over {@link 088 * Collections#singleton} for code consistency, {@code null} rejection, and because the return 089 * type conveys the immutability guarantee. 090 */ 091 public static <E> ImmutableSet<E> of(E element) { 092 return new SingletonImmutableSet<E>(element); 093 } 094 095 /** 096 * Returns an immutable set containing the given elements, minus duplicates, in the order each was 097 * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except 098 * the first are ignored. 099 */ 100 public static <E> ImmutableSet<E> of(E e1, E e2) { 101 return construct(2, 2, e1, e2); 102 } 103 104 /** 105 * Returns an immutable set containing the given elements, minus duplicates, in the order each was 106 * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except 107 * the first are ignored. 108 */ 109 public static <E> ImmutableSet<E> of(E e1, E e2, E e3) { 110 return construct(3, 3, e1, e2, e3); 111 } 112 113 /** 114 * Returns an immutable set containing the given elements, minus duplicates, in the order each was 115 * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except 116 * the first are ignored. 117 */ 118 public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4) { 119 return construct(4, 4, e1, e2, e3, e4); 120 } 121 122 /** 123 * Returns an immutable set containing the given elements, minus duplicates, in the order each was 124 * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except 125 * the first are ignored. 126 */ 127 public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5) { 128 return construct(5, 5, e1, e2, e3, e4, e5); 129 } 130 131 /** 132 * Returns an immutable set containing the given elements, minus duplicates, in the order each was 133 * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except 134 * the first are ignored. 135 * 136 * <p>The array {@code others} must not be longer than {@code Integer.MAX_VALUE - 6}. 137 * 138 * @since 3.0 (source-compatible since 2.0) 139 */ 140 @SafeVarargs // For Eclipse. For internal javac we have disabled this pointless type of warning. 141 public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) { 142 checkArgument( 143 others.length <= Integer.MAX_VALUE - 6, "the total number of elements must fit in an int"); 144 final int paramCount = 6; 145 Object[] elements = new Object[paramCount + others.length]; 146 elements[0] = e1; 147 elements[1] = e2; 148 elements[2] = e3; 149 elements[3] = e4; 150 elements[4] = e5; 151 elements[5] = e6; 152 System.arraycopy(others, 0, elements, paramCount, others.length); 153 return construct(elements.length, elements.length, elements); 154 } 155 156 /** 157 * Constructs an {@code ImmutableSet} from the first {@code n} elements of the specified array, 158 * which we have no particular reason to believe does or does not contain duplicates. If {@code k} 159 * is the size of the returned {@code ImmutableSet}, then the unique elements of {@code elements} 160 * will be in the first {@code k} positions, and {@code elements[i] == null} for {@code k <= i < 161 * n}. 162 * 163 * <p>This may modify {@code elements}. Additionally, if {@code n == elements.length} and {@code 164 * elements} contains no duplicates, {@code elements} may be used without copying in the returned 165 * {@code ImmutableSet}, in which case the caller must not modify it. 166 * 167 * <p>{@code elements} may contain only values of type {@code E}. 168 * 169 * @throws NullPointerException if any of the first {@code n} elements of {@code elements} is null 170 */ 171 private static <E> ImmutableSet<E> constructUnknownDuplication(int n, Object... elements) { 172 // Guess the size is "halfway between" all duplicates and no duplicates, on a log scale. 173 return construct( 174 n, 175 Math.max( 176 ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY, 177 IntMath.sqrt(n, RoundingMode.CEILING)), 178 elements); 179 } 180 181 /** 182 * Constructs an {@code ImmutableSet} from the first {@code n} elements of the specified array. If 183 * {@code k} is the size of the returned {@code ImmutableSet}, then the unique elements of {@code 184 * elements} will be in the first {@code k} positions, and {@code elements[i] == null} for {@code 185 * k <= i < n}. 186 * 187 * <p>This may modify {@code elements}. Additionally, if {@code n == elements.length} and {@code 188 * elements} contains no duplicates, {@code elements} may be used without copying in the returned 189 * {@code ImmutableSet}, in which case it may no longer be modified. 190 * 191 * <p>{@code elements} may contain only values of type {@code E}. 192 * 193 * @throws NullPointerException if any of the first {@code n} elements of {@code elements} is null 194 */ 195 private static <E> ImmutableSet<E> construct(int n, int expectedSize, Object... elements) { 196 switch (n) { 197 case 0: 198 return of(); 199 case 1: 200 @SuppressWarnings("unchecked") // safe; elements contains only E's 201 E elem = (E) elements[0]; 202 return of(elem); 203 default: 204 SetBuilderImpl<E> builder = new RegularSetBuilderImpl<E>(expectedSize); 205 for (int i = 0; i < n; i++) { 206 @SuppressWarnings("unchecked") 207 E e = (E) checkNotNull(elements[i]); 208 builder = builder.add(e); 209 } 210 return builder.review().build(); 211 } 212 } 213 214 /** 215 * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order 216 * each appears first in the source collection. 217 * 218 * <p><b>Performance note:</b> This method will sometimes recognize that the actual copy operation 219 * is unnecessary; for example, {@code copyOf(copyOf(anArrayList))} will copy the data only once. 220 * This reduces the expense of habitually making defensive copies at API boundaries. However, the 221 * precise conditions for skipping the copy operation are undefined. 222 * 223 * @throws NullPointerException if any of {@code elements} is null 224 * @since 7.0 (source-compatible since 2.0) 225 */ 226 public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) { 227 /* 228 * TODO(lowasser): consider checking for ImmutableAsList here 229 * TODO(lowasser): consider checking for Multiset here 230 */ 231 // Don't refer to ImmutableSortedSet by name so it won't pull in all that code 232 if (elements instanceof ImmutableSet && !(elements instanceof SortedSet)) { 233 @SuppressWarnings("unchecked") // all supported methods are covariant 234 ImmutableSet<E> set = (ImmutableSet<E>) elements; 235 if (!set.isPartialView()) { 236 return set; 237 } 238 } else if (elements instanceof EnumSet) { 239 return copyOfEnumSet((EnumSet) elements); 240 } 241 Object[] array = elements.toArray(); 242 if (elements instanceof Set) { 243 // assume probably no duplicates (though it might be using different equality semantics) 244 return construct(array.length, array.length, array); 245 } else { 246 return constructUnknownDuplication(array.length, array); 247 } 248 } 249 250 /** 251 * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order 252 * each appears first in the source iterable. This method iterates over {@code elements} only 253 * once. 254 * 255 * <p><b>Performance note:</b> This method will sometimes recognize that the actual copy operation 256 * is unnecessary; for example, {@code copyOf(copyOf(anArrayList))} should copy the data only 257 * once. This reduces the expense of habitually making defensive copies at API boundaries. 258 * However, the precise conditions for skipping the copy operation are undefined. 259 * 260 * @throws NullPointerException if any of {@code elements} is null 261 */ 262 public static <E> ImmutableSet<E> copyOf(Iterable<? extends E> elements) { 263 return (elements instanceof Collection) 264 ? copyOf((Collection<? extends E>) elements) 265 : copyOf(elements.iterator()); 266 } 267 268 /** 269 * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order 270 * each appears first in the source iterator. 271 * 272 * @throws NullPointerException if any of {@code elements} is null 273 */ 274 public static <E> ImmutableSet<E> copyOf(Iterator<? extends E> elements) { 275 // We special-case for 0 or 1 elements, but anything further is madness. 276 if (!elements.hasNext()) { 277 return of(); 278 } 279 E first = elements.next(); 280 if (!elements.hasNext()) { 281 return of(first); 282 } else { 283 return new ImmutableSet.Builder<E>().add(first).addAll(elements).build(); 284 } 285 } 286 287 /** 288 * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order 289 * each appears first in the source array. 290 * 291 * @throws NullPointerException if any of {@code elements} is null 292 * @since 3.0 293 */ 294 public static <E> ImmutableSet<E> copyOf(E[] elements) { 295 switch (elements.length) { 296 case 0: 297 return of(); 298 case 1: 299 return of(elements[0]); 300 default: 301 return constructUnknownDuplication(elements.length, elements.clone()); 302 } 303 } 304 305 @SuppressWarnings("rawtypes") // necessary to compile against Java 8 306 private static ImmutableSet copyOfEnumSet(EnumSet enumSet) { 307 return ImmutableEnumSet.asImmutable(EnumSet.copyOf(enumSet)); 308 } 309 310 ImmutableSet() {} 311 312 /** Returns {@code true} if the {@code hashCode()} method runs quickly. */ 313 boolean isHashCodeFast() { 314 return false; 315 } 316 317 @Override 318 public boolean equals(@CheckForNull Object object) { 319 if (object == this) { 320 return true; 321 } 322 if (object instanceof ImmutableSet 323 && isHashCodeFast() 324 && ((ImmutableSet<?>) object).isHashCodeFast() 325 && hashCode() != object.hashCode()) { 326 return false; 327 } 328 return Sets.equalsImpl(this, object); 329 } 330 331 @Override 332 public int hashCode() { 333 return Sets.hashCodeImpl(this); 334 } 335 336 // This declaration is needed to make Set.iterator() and 337 // ImmutableCollection.iterator() consistent. 338 @Override 339 public abstract UnmodifiableIterator<E> iterator(); 340 341 @GwtCompatible 342 abstract static class CachingAsList<E> extends ImmutableSet<E> { 343 @LazyInit @RetainedWith @CheckForNull private transient ImmutableList<E> asList; 344 345 @Override 346 public ImmutableList<E> asList() { 347 ImmutableList<E> result = asList; 348 if (result == null) { 349 return asList = createAsList(); 350 } else { 351 return result; 352 } 353 } 354 355 ImmutableList<E> createAsList() { 356 return new RegularImmutableAsList<E>(this, toArray()); 357 } 358 359 // redeclare to help optimizers with b/310253115 360 @SuppressWarnings("RedundantOverride") 361 @Override 362 @J2ktIncompatible // serialization 363 @GwtIncompatible // serialization 364 Object writeReplace() { 365 return super.writeReplace(); 366 } 367 } 368 369 abstract static class Indexed<E> extends CachingAsList<E> { 370 abstract E get(int index); 371 372 @Override 373 public UnmodifiableIterator<E> iterator() { 374 return asList().iterator(); 375 } 376 377 @Override 378 public Spliterator<E> spliterator() { 379 return CollectSpliterators.indexed(size(), SPLITERATOR_CHARACTERISTICS, this::get); 380 } 381 382 @Override 383 public void forEach(Consumer<? super E> consumer) { 384 checkNotNull(consumer); 385 int n = size(); 386 for (int i = 0; i < n; i++) { 387 consumer.accept(get(i)); 388 } 389 } 390 391 @Override 392 int copyIntoArray(@Nullable Object[] dst, int offset) { 393 return asList().copyIntoArray(dst, offset); 394 } 395 396 @Override 397 ImmutableList<E> createAsList() { 398 return new ImmutableAsList<E>() { 399 @Override 400 public E get(int index) { 401 return Indexed.this.get(index); 402 } 403 404 @Override 405 Indexed<E> delegateCollection() { 406 return Indexed.this; 407 } 408 409 // redeclare to help optimizers with b/310253115 410 @SuppressWarnings("RedundantOverride") 411 @Override 412 @J2ktIncompatible // serialization 413 @GwtIncompatible // serialization 414 Object writeReplace() { 415 return super.writeReplace(); 416 } 417 }; 418 } 419 420 // redeclare to help optimizers with b/310253115 421 @SuppressWarnings("RedundantOverride") 422 @Override 423 @J2ktIncompatible // serialization 424 @GwtIncompatible // serialization 425 Object writeReplace() { 426 return super.writeReplace(); 427 } 428 } 429 430 /* 431 * This class is used to serialize all ImmutableSet instances, except for 432 * ImmutableEnumSet/ImmutableSortedSet, regardless of implementation type. It 433 * captures their "logical contents" and they are reconstructed using public 434 * static factories. This is necessary to ensure that the existence of a 435 * particular implementation type is an implementation detail. 436 */ 437 @J2ktIncompatible // serialization 438 private static class SerializedForm implements Serializable { 439 final Object[] elements; 440 441 SerializedForm(Object[] elements) { 442 this.elements = elements; 443 } 444 445 Object readResolve() { 446 return copyOf(elements); 447 } 448 449 private static final long serialVersionUID = 0; 450 } 451 452 @Override 453 @J2ktIncompatible // serialization 454 Object writeReplace() { 455 return new SerializedForm(toArray()); 456 } 457 458 @J2ktIncompatible // serialization 459 private void readObject(ObjectInputStream stream) throws InvalidObjectException { 460 throw new InvalidObjectException("Use SerializedForm"); 461 } 462 463 /** 464 * Returns a new builder. The generated builder is equivalent to the builder created by the {@link 465 * Builder} constructor. 466 */ 467 public static <E> Builder<E> builder() { 468 return new Builder<E>(); 469 } 470 471 /** 472 * Returns a new builder, expecting the specified number of distinct elements to be added. 473 * 474 * <p>If {@code expectedSize} is exactly the number of distinct elements added to the builder 475 * before {@link Builder#build} is called, the builder is likely to perform better than an unsized 476 * {@link #builder()} would have. 477 * 478 * <p>It is not specified if any performance benefits apply if {@code expectedSize} is close to, 479 * but not exactly, the number of distinct elements added to the builder. 480 * 481 * @since 23.1 482 */ 483 public static <E> Builder<E> builderWithExpectedSize(int expectedSize) { 484 checkNonnegative(expectedSize, "expectedSize"); 485 return new Builder<E>(expectedSize); 486 } 487 488 /** 489 * A builder for creating {@code ImmutableSet} instances. Example: 490 * 491 * <pre>{@code 492 * static final ImmutableSet<Color> GOOGLE_COLORS = 493 * ImmutableSet.<Color>builder() 494 * .addAll(WEBSAFE_COLORS) 495 * .add(new Color(0, 191, 255)) 496 * .build(); 497 * }</pre> 498 * 499 * <p>Elements appear in the resulting set in the same order they were first added to the builder. 500 * 501 * <p>Building does not change the state of the builder, so it is still possible to add more 502 * elements and to build again. 503 * 504 * @since 2.0 505 */ 506 public static class Builder<E> extends ImmutableCollection.Builder<E> { 507 /* 508 * `impl` is null only for instances of the subclass, ImmutableSortedSet.Builder. That subclass 509 * overrides all the methods that access it here. Thus, all the methods here can safely assume 510 * that this field is non-null. 511 */ 512 @CheckForNull private SetBuilderImpl<E> impl; 513 boolean forceCopy; 514 515 public Builder() { 516 this(0); 517 } 518 519 Builder(int capacity) { 520 if (capacity > 0) { 521 impl = new RegularSetBuilderImpl<E>(capacity); 522 } else { 523 impl = EmptySetBuilderImpl.instance(); 524 } 525 } 526 527 Builder(@SuppressWarnings("unused") boolean subclass) { 528 this.impl = null; // unused 529 } 530 531 @VisibleForTesting 532 void forceJdk() { 533 requireNonNull(impl); // see the comment on the field 534 this.impl = new JdkBackedSetBuilderImpl<E>(impl); 535 } 536 537 final void copyIfNecessary() { 538 if (forceCopy) { 539 copy(); 540 forceCopy = false; 541 } 542 } 543 544 void copy() { 545 requireNonNull(impl); // see the comment on the field 546 impl = impl.copy(); 547 } 548 549 @Override 550 @CanIgnoreReturnValue 551 public Builder<E> add(E element) { 552 requireNonNull(impl); // see the comment on the field 553 checkNotNull(element); 554 copyIfNecessary(); 555 impl = impl.add(element); 556 return this; 557 } 558 559 @Override 560 @CanIgnoreReturnValue 561 public Builder<E> add(E... elements) { 562 super.add(elements); 563 return this; 564 } 565 566 /** 567 * Adds each element of {@code elements} to the {@code ImmutableSet}, ignoring duplicate 568 * elements (only the first duplicate element is added). 569 * 570 * @param elements the elements to add 571 * @return this {@code Builder} object 572 * @throws NullPointerException if {@code elements} is null or contains a null element 573 */ 574 @Override 575 @CanIgnoreReturnValue 576 public Builder<E> addAll(Iterable<? extends E> elements) { 577 super.addAll(elements); 578 return this; 579 } 580 581 @Override 582 @CanIgnoreReturnValue 583 public Builder<E> addAll(Iterator<? extends E> elements) { 584 super.addAll(elements); 585 return this; 586 } 587 588 @CanIgnoreReturnValue 589 Builder<E> combine(Builder<E> other) { 590 requireNonNull(impl); 591 requireNonNull(other.impl); 592 /* 593 * For discussion of requireNonNull, see the comment on the field. 594 * 595 * (And I don't believe there's any situation in which we call x.combine(y) when x is a plain 596 * ImmutableSet.Builder but y is an ImmutableSortedSet.Builder (or vice versa). Certainly 597 * ImmutableSortedSet.Builder.combine() is written as if its argument will never be a plain 598 * ImmutableSet.Builder: It casts immediately to ImmutableSortedSet.Builder.) 599 */ 600 copyIfNecessary(); 601 this.impl = this.impl.combine(other.impl); 602 return this; 603 } 604 605 @Override 606 public ImmutableSet<E> build() { 607 requireNonNull(impl); // see the comment on the field 608 forceCopy = true; 609 impl = impl.review(); 610 return impl.build(); 611 } 612 } 613 614 /** Swappable internal implementation of an ImmutableSet.Builder. */ 615 private abstract static class SetBuilderImpl<E> { 616 // The first `distinct` elements are non-null. 617 // Since we can never access null elements, we don't mark this nullable. 618 E[] dedupedElements; 619 int distinct; 620 621 @SuppressWarnings("unchecked") 622 SetBuilderImpl(int expectedCapacity) { 623 this.dedupedElements = (E[]) new Object[expectedCapacity]; 624 this.distinct = 0; 625 } 626 627 /** Initializes this SetBuilderImpl with a copy of the deduped elements array from toCopy. */ 628 SetBuilderImpl(SetBuilderImpl<E> toCopy) { 629 this.dedupedElements = Arrays.copyOf(toCopy.dedupedElements, toCopy.dedupedElements.length); 630 this.distinct = toCopy.distinct; 631 } 632 633 /** 634 * Resizes internal data structures if necessary to store the specified number of distinct 635 * elements. 636 */ 637 private void ensureCapacity(int minCapacity) { 638 if (minCapacity > dedupedElements.length) { 639 int newCapacity = 640 ImmutableCollection.Builder.expandedCapacity(dedupedElements.length, minCapacity); 641 dedupedElements = Arrays.copyOf(dedupedElements, newCapacity); 642 } 643 } 644 645 /** Adds e to the insertion-order array of deduplicated elements. Calls ensureCapacity. */ 646 final void addDedupedElement(E e) { 647 ensureCapacity(distinct + 1); 648 dedupedElements[distinct++] = e; 649 } 650 651 /** 652 * Adds e to this SetBuilderImpl, returning the updated result. Only use the returned 653 * SetBuilderImpl, since we may switch implementations if e.g. hash flooding is detected. 654 */ 655 abstract SetBuilderImpl<E> add(E e); 656 657 /** Adds all the elements from the specified SetBuilderImpl to this SetBuilderImpl. */ 658 final SetBuilderImpl<E> combine(SetBuilderImpl<E> other) { 659 SetBuilderImpl<E> result = this; 660 for (int i = 0; i < other.distinct; i++) { 661 /* 662 * requireNonNull is safe because we ensure that the first `distinct` elements have been 663 * populated. 664 */ 665 result = result.add(requireNonNull(other.dedupedElements[i])); 666 } 667 return result; 668 } 669 670 /** 671 * Creates a new copy of this SetBuilderImpl. Modifications to that SetBuilderImpl will not 672 * affect this SetBuilderImpl or sets constructed from this SetBuilderImpl via build(). 673 */ 674 abstract SetBuilderImpl<E> copy(); 675 676 /** 677 * Call this before build(). Does a final check on the internal data structures, e.g. shrinking 678 * unnecessarily large structures or detecting previously unnoticed hash flooding. 679 */ 680 SetBuilderImpl<E> review() { 681 return this; 682 } 683 684 abstract ImmutableSet<E> build(); 685 } 686 687 private static final class EmptySetBuilderImpl<E> extends SetBuilderImpl<E> { 688 private static final EmptySetBuilderImpl<Object> INSTANCE = new EmptySetBuilderImpl<>(); 689 690 @SuppressWarnings("unchecked") 691 static <E> SetBuilderImpl<E> instance() { 692 return (SetBuilderImpl<E>) INSTANCE; 693 } 694 695 private EmptySetBuilderImpl() { 696 super(0); 697 } 698 699 @Override 700 SetBuilderImpl<E> add(E e) { 701 return new RegularSetBuilderImpl<E>(Builder.DEFAULT_INITIAL_CAPACITY).add(e); 702 } 703 704 @Override 705 SetBuilderImpl<E> copy() { 706 return this; 707 } 708 709 @Override 710 ImmutableSet<E> build() { 711 return ImmutableSet.of(); 712 } 713 } 714 715 // We use power-of-2 tables, and this is the highest int that's a power of 2 716 static final int MAX_TABLE_SIZE = Ints.MAX_POWER_OF_TWO; 717 718 // Represents how tightly we can pack things, as a maximum. 719 private static final double DESIRED_LOAD_FACTOR = 0.7; 720 721 // If the set has this many elements, it will "max out" the table size 722 private static final int CUTOFF = (int) (MAX_TABLE_SIZE * DESIRED_LOAD_FACTOR); 723 724 /** 725 * Returns an array size suitable for the backing array of a hash table that uses open addressing 726 * with linear probing in its implementation. The returned size is the smallest power of two that 727 * can hold setSize elements with the desired load factor. Always returns at least setSize + 2. 728 */ 729 // TODO(cpovirk): Move to Hashing or something, since it's used elsewhere in the Android version. 730 static int chooseTableSize(int setSize) { 731 setSize = Math.max(setSize, 2); 732 // Correct the size for open addressing to match desired load factor. 733 if (setSize < CUTOFF) { 734 // Round up to the next highest power of 2. 735 int tableSize = Integer.highestOneBit(setSize - 1) << 1; 736 while (tableSize * DESIRED_LOAD_FACTOR < setSize) { 737 tableSize <<= 1; 738 } 739 return tableSize; 740 } 741 742 // The table can't be completely full or we'll get infinite reprobes 743 checkArgument(setSize < MAX_TABLE_SIZE, "collection too large"); 744 return MAX_TABLE_SIZE; 745 } 746 747 /** 748 * Default implementation of the guts of ImmutableSet.Builder, creating an open-addressed hash 749 * table and deduplicating elements as they come, so it only allocates O(max(distinct, 750 * expectedCapacity)) rather than O(calls to add). 751 * 752 * <p>This implementation attempts to detect hash flooding, and if it's identified, falls back to 753 * JdkBackedSetBuilderImpl. 754 */ 755 private static final class RegularSetBuilderImpl<E> extends SetBuilderImpl<E> { 756 // null until at least two elements are present 757 @CheckForNull private @Nullable Object[] hashTable; 758 private int maxRunBeforeFallback; 759 private int expandTableThreshold; 760 private int hashCode; 761 762 RegularSetBuilderImpl(int expectedCapacity) { 763 super(expectedCapacity); 764 this.hashTable = null; 765 this.maxRunBeforeFallback = 0; 766 this.expandTableThreshold = 0; 767 } 768 769 RegularSetBuilderImpl(RegularSetBuilderImpl<E> toCopy) { 770 super(toCopy); 771 this.hashTable = (toCopy.hashTable == null) ? null : toCopy.hashTable.clone(); 772 this.maxRunBeforeFallback = toCopy.maxRunBeforeFallback; 773 this.expandTableThreshold = toCopy.expandTableThreshold; 774 this.hashCode = toCopy.hashCode; 775 } 776 777 @Override 778 SetBuilderImpl<E> add(E e) { 779 checkNotNull(e); 780 if (hashTable == null) { 781 if (distinct == 0) { 782 addDedupedElement(e); 783 return this; 784 } else { 785 ensureTableCapacity(dedupedElements.length); 786 E elem = dedupedElements[0]; 787 distinct--; 788 return insertInHashTable(elem).add(e); 789 } 790 } 791 return insertInHashTable(e); 792 } 793 794 private SetBuilderImpl<E> insertInHashTable(E e) { 795 requireNonNull(hashTable); 796 int eHash = e.hashCode(); 797 int i0 = Hashing.smear(eHash); 798 int mask = hashTable.length - 1; 799 for (int i = i0; i - i0 < maxRunBeforeFallback; i++) { 800 int index = i & mask; 801 Object tableEntry = hashTable[index]; 802 if (tableEntry == null) { 803 addDedupedElement(e); 804 hashTable[index] = e; 805 hashCode += eHash; 806 ensureTableCapacity(distinct); // rebuilds table if necessary 807 return this; 808 } else if (tableEntry.equals(e)) { // not a new element, ignore 809 return this; 810 } 811 } 812 // we fell out of the loop due to a long run; fall back to JDK impl 813 return new JdkBackedSetBuilderImpl<E>(this).add(e); 814 } 815 816 @Override 817 SetBuilderImpl<E> copy() { 818 return new RegularSetBuilderImpl<E>(this); 819 } 820 821 @Override 822 SetBuilderImpl<E> review() { 823 if (hashTable == null) { 824 return this; 825 } 826 int targetTableSize = chooseTableSize(distinct); 827 if (targetTableSize * 2 < hashTable.length) { 828 hashTable = rebuildHashTable(targetTableSize, dedupedElements, distinct); 829 maxRunBeforeFallback = maxRunBeforeFallback(targetTableSize); 830 expandTableThreshold = (int) (DESIRED_LOAD_FACTOR * targetTableSize); 831 } 832 return hashFloodingDetected(hashTable) ? new JdkBackedSetBuilderImpl<E>(this) : this; 833 } 834 835 @Override 836 ImmutableSet<E> build() { 837 switch (distinct) { 838 case 0: 839 return of(); 840 case 1: 841 /* 842 * requireNonNull is safe because we ensure that the first `distinct` elements have been 843 * populated. 844 */ 845 return of(requireNonNull(dedupedElements[0])); 846 default: 847 /* 848 * The suppression is safe because we ensure that the first `distinct` elements have been 849 * populated. 850 */ 851 @SuppressWarnings("nullness") 852 Object[] elements = 853 (distinct == dedupedElements.length) 854 ? dedupedElements 855 : Arrays.copyOf(dedupedElements, distinct); 856 return new RegularImmutableSet<E>( 857 elements, hashCode, requireNonNull(hashTable), hashTable.length - 1); 858 } 859 } 860 861 /** Builds a new open-addressed hash table from the first n objects in elements. */ 862 static @Nullable Object[] rebuildHashTable(int newTableSize, Object[] elements, int n) { 863 @Nullable Object[] hashTable = new @Nullable Object[newTableSize]; 864 int mask = hashTable.length - 1; 865 for (int i = 0; i < n; i++) { 866 // requireNonNull is safe because we ensure that the first n elements have been populated. 867 Object e = requireNonNull(elements[i]); 868 int j0 = Hashing.smear(e.hashCode()); 869 for (int j = j0; ; j++) { 870 int index = j & mask; 871 if (hashTable[index] == null) { 872 hashTable[index] = e; 873 break; 874 } 875 } 876 } 877 return hashTable; 878 } 879 880 void ensureTableCapacity(int minCapacity) { 881 int newTableSize; 882 if (hashTable == null) { 883 newTableSize = chooseTableSize(minCapacity); 884 hashTable = new Object[newTableSize]; 885 } else if (minCapacity > expandTableThreshold && hashTable.length < MAX_TABLE_SIZE) { 886 newTableSize = hashTable.length * 2; 887 hashTable = rebuildHashTable(newTableSize, dedupedElements, distinct); 888 } else { 889 return; 890 } 891 maxRunBeforeFallback = maxRunBeforeFallback(newTableSize); 892 expandTableThreshold = (int) (DESIRED_LOAD_FACTOR * newTableSize); 893 } 894 895 /** 896 * We attempt to detect deliberate hash flooding attempts. If one is detected, we fall back to a 897 * wrapper around j.u.HashSet, which has built-in flooding protection. MAX_RUN_MULTIPLIER was 898 * determined experimentally to match our desired probability of false positives. 899 */ 900 // NB: yes, this is surprisingly high, but that's what the experiments said was necessary 901 // Raising this number slows the worst-case contains behavior, speeds up hashFloodingDetected, 902 // and reduces the false-positive probability. 903 static final int MAX_RUN_MULTIPLIER = 13; 904 905 /** 906 * Checks the whole hash table for poor hash distribution. Takes O(n) in the worst case, O(n / 907 * log n) on average. 908 * 909 * <p>The online hash flooding detecting in RegularSetBuilderImpl.add can detect e.g. many 910 * exactly matching hash codes, which would cause construction to take O(n^2), but can't detect 911 * e.g. hash codes adversarially designed to go into ascending table locations, which keeps 912 * construction O(n) (as desired) but then can have O(n) queries later. 913 * 914 * <p>If this returns false, then no query can take more than O(log n). 915 * 916 * <p>Note that for a RegularImmutableSet with elements with truly random hash codes, contains 917 * operations take expected O(1) time but with high probability take O(log n) for at least some 918 * element. (https://en.wikipedia.org/wiki/Linear_probing#Analysis) 919 * 920 * <p>This method may return {@code true} even on truly random input, but {@code 921 * ImmutableSetTest} tests that the probability of that is low. 922 */ 923 static boolean hashFloodingDetected(@Nullable Object[] hashTable) { 924 int maxRunBeforeFallback = maxRunBeforeFallback(hashTable.length); 925 int mask = hashTable.length - 1; 926 927 // Invariant: all elements at indices in [knownRunStart, knownRunEnd) are nonnull. 928 // If knownRunStart == knownRunEnd, this is vacuously true. 929 // When knownRunEnd exceeds hashTable.length, it "wraps", detecting runs around the end 930 // of the table. 931 int knownRunStart = 0; 932 int knownRunEnd = 0; 933 934 outerLoop: 935 while (knownRunStart < hashTable.length) { 936 if (knownRunStart == knownRunEnd && hashTable[knownRunStart] == null) { 937 if (hashTable[(knownRunStart + maxRunBeforeFallback - 1) & mask] == null) { 938 // There are only maxRunBeforeFallback - 1 elements between here and there, 939 // so even if they were all nonnull, we wouldn't detect a hash flood. Therefore, 940 // we can skip them all. 941 knownRunStart += maxRunBeforeFallback; 942 } else { 943 knownRunStart++; // the only case in which maxRunEnd doesn't increase by mRBF 944 // happens about f * (1-f) for f = DESIRED_LOAD_FACTOR, so around 21% of the time 945 } 946 knownRunEnd = knownRunStart; 947 } else { 948 for (int j = knownRunStart + maxRunBeforeFallback - 1; j >= knownRunEnd; j--) { 949 if (hashTable[j & mask] == null) { 950 knownRunEnd = knownRunStart + maxRunBeforeFallback; 951 knownRunStart = j + 1; 952 continue outerLoop; 953 } 954 } 955 return true; 956 } 957 } 958 return false; 959 } 960 961 /** 962 * If more than this many consecutive positions are filled in a table of the specified size, 963 * report probable hash flooding. ({@link #hashFloodingDetected} may also report hash flooding 964 * if fewer consecutive positions are filled; see that method for details.) 965 */ 966 static int maxRunBeforeFallback(int tableSize) { 967 return MAX_RUN_MULTIPLIER * IntMath.log2(tableSize, RoundingMode.UNNECESSARY); 968 } 969 } 970 971 /** 972 * SetBuilderImpl version that uses a JDK HashSet, which has built in hash flooding protection. 973 */ 974 private static final class JdkBackedSetBuilderImpl<E> extends SetBuilderImpl<E> { 975 private final Set<Object> delegate; 976 977 JdkBackedSetBuilderImpl(SetBuilderImpl<E> toCopy) { 978 super(toCopy); // initializes dedupedElements and distinct 979 delegate = Sets.newHashSetWithExpectedSize(distinct); 980 for (int i = 0; i < distinct; i++) { 981 /* 982 * requireNonNull is safe because we ensure that the first `distinct` elements have been 983 * populated. 984 */ 985 delegate.add(requireNonNull(dedupedElements[i])); 986 } 987 } 988 989 @Override 990 SetBuilderImpl<E> add(E e) { 991 checkNotNull(e); 992 if (delegate.add(e)) { 993 addDedupedElement(e); 994 } 995 return this; 996 } 997 998 @Override 999 SetBuilderImpl<E> copy() { 1000 return new JdkBackedSetBuilderImpl<>(this); 1001 } 1002 1003 @Override 1004 ImmutableSet<E> build() { 1005 switch (distinct) { 1006 case 0: 1007 return of(); 1008 case 1: 1009 /* 1010 * requireNonNull is safe because we ensure that the first `distinct` elements have been 1011 * populated. 1012 */ 1013 return of(requireNonNull(dedupedElements[0])); 1014 default: 1015 return new JdkBackedImmutableSet<E>( 1016 delegate, ImmutableList.asImmutableList(dedupedElements, distinct)); 1017 } 1018 } 1019 } 1020 1021 private static final long serialVersionUID = 0xcafebabe; 1022}