public static double estimateNumberOfHashCollisions(int numberOfValues, int hashSize)
    {
        checkState(0 <= numberOfValues && numberOfValues <= hashSize);

        if (hashSize == 0) {
            return 0d;
        }

        double estimateRescaleFactor = (double) numberOfValues / NUMBER_OF_VALUES;
        double estimateIndex = (double) NUMBER_OF_ESTIMATES * numberOfValues / hashSize;
        int lowerEstimateIndex = (int) floor(estimateIndex);
        int upperEstimateIndex = (int) ceil(estimateIndex);

        if (lowerEstimateIndex == upperEstimateIndex) {
            return COLLISION_ESTIMATES[lowerEstimateIndex] * estimateRescaleFactor;
        }

        double lowerEstimation = COLLISION_ESTIMATES[lowerEstimateIndex];
        double upperEstimation = COLLISION_ESTIMATES[upperEstimateIndex];
        double estimationIndexDistanceFromLower = estimateIndex - lowerEstimateIndex;

        return (lowerEstimation * (1 - estimationIndexDistanceFromLower) + upperEstimation * estimationIndexDistanceFromLower) * estimateRescaleFactor;
    }
@Test
    public void hashEstimatesShouldIncrease()
    {
        assertEquals(estimateNumberOfHashCollisions(0, 100), 0d);
        for (int i = 1; i <= HASH_TABLE_SIZE; ++i) {
            assertTrue(estimateNumberOfHashCollisions(i - 1, HASH_TABLE_SIZE) < estimateNumberOfHashCollisions(i, HASH_TABLE_SIZE));
        }
    }