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