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