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