guava/src/com/google/common/collect/ImmutableSet.java
static boolean hashFloodingDetected(Object[] hashTable) {
    int maxRunBeforeFallback = maxRunBeforeFallback(hashTable.length);

    // Test for a run wrapping around the end of the table of length at least maxRunBeforeFallback.
    int endOfStartRun;
    for (endOfStartRun = 0; endOfStartRun < hashTable.length; ) {
      if (hashTable[endOfStartRun] == null) {
        break;
      }
      endOfStartRun++;
      if (endOfStartRun > maxRunBeforeFallback) {
        return true;
      }
    }
    int startOfEndRun;
    for (startOfEndRun = hashTable.length - 1; startOfEndRun > endOfStartRun; startOfEndRun--) {
      if (hashTable[startOfEndRun] == null) {
        break;
      }
      if (endOfStartRun + (hashTable.length - 1 - startOfEndRun) > maxRunBeforeFallback) {
        return true;
      }
    }

    // Now, break the remainder of the table into blocks of maxRunBeforeFallback/2 elements and
    // check that each has at least one null.
    int testBlockSize = maxRunBeforeFallback / 2;
    blockLoop:
    for (int i = endOfStartRun + 1; i + testBlockSize <= startOfEndRun; i += testBlockSize) {
      for (int j = 0; j < testBlockSize; j++) {
        if (hashTable[i + j] == null) {
          continue blockLoop;
        }
      }
      return true;
    }
    return false;
  }
static boolean hashFloodingDetected(Object[] hashTable) {
    int maxRunBeforeFallback = maxRunBeforeFallback(hashTable.length);

    // Test for a run wrapping around the end of the table of length at least maxRunBeforeFallback.
    int endOfStartRun;
    for (endOfStartRun = 0; endOfStartRun < hashTable.length; ) {
      if (hashTable[endOfStartRun] == null) {
        break;
      }
      endOfStartRun++;
      if (endOfStartRun > maxRunBeforeFallback) {
        return true;
      }
    }
    int startOfEndRun;
    for (startOfEndRun = hashTable.length - 1; startOfEndRun > endOfStartRun; startOfEndRun--) {
      if (hashTable[startOfEndRun] == null) {
        break;
      }
      if (endOfStartRun + (hashTable.length - 1 - startOfEndRun) > maxRunBeforeFallback) {
        return true;
      }
    }

    // Now, break the remainder of the table into blocks of maxRunBeforeFallback/2 elements and
    // check that each has at least one null.
    int testBlockSize = maxRunBeforeFallback / 2;
    blockLoop:
    for (int i = endOfStartRun + 1; i + testBlockSize <= startOfEndRun; i += testBlockSize) {
      for (int j = 0; j < testBlockSize; j++) {
        if (hashTable[i + j] == null) {
          continue blockLoop;
        }
      }
      return true;
    }
    return false;
  }
Checks the whole hash table for poor hash distribution. Takes O(n) in the worst case, O(n / log
n) on average.

<p>The online hash flooding detecting in RegularSetBuilderImpl.add can detect e.g. many exactly
matching hash codes, which would cause construction to take O(n^2), but can't detect e.g. hash
codes adversarially designed to go into ascending table locations, which keeps construction
O(n) (as desired) but then can have O(n) queries later.

<p>If this returns false, then no query can take more than O(log n).

<p>Note that for a RegularImmutableSet with elements with truly random hash codes, contains
operations take expected O(1) time but with high probability take O(log n) for at least some
element. (https://en.wikipedia.org/wiki/Linear_probing#Analysis)

<p>This method may return {@code true} up to {@link #HASH_FLOODING_FPP} of the time even on
truly random input.

<p>If this method returns false, there are definitely no runs of length at least {@code
maxRunBeforeFallback(hashTable.length)} nonnull elements. If there are no runs of length at
least {@code maxRunBeforeFallback(hashTable.length) / 2} nonnull elements, this method
definitely returns false. In between those constraints, the result of this method is undefined,
subject to the above {@link #HASH_FLOODING_FPP} constraint.