(See the previous version here.)

This time, I have encorporated all the suggestions made by Marc. Also, I changed the type of points from `double`

to `Number`

. My newest version follows:

`com.github.coderodde.codereview.notepad.ClusternessMeasure`

```
package com.github.coderodde.codereview.notepad;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
/**
* This class implements a method for computing clusterness measure (CM). CM
* asks for a set of points {@code x_1, x_2, ..., x_n}, and it returns a
* number within {@code (0, 1)}. The idea behind CM is that it returns 0 when
* all the data points are equal and 1 whenever all adjacent points are
* equidistant.
*
* @author Rodion "rodde" Efremov
* @version 1.618 (Jun 11, 2019)
* @since 1.6 (Feb 21, 2019)
*/
public final class ClusternessMeasure {
/**
* Computes the clusterness measure of the input points.
* @param points the points to process.
* @return the number within range {@code (0, 1)}, describing how clustered
* the input points are.
*/
public static double computeClusternessMeasure(Collection<Number> points) {
return computeClusternessMeasure(
new SortedMeasurementPoints(
Objects.requireNonNull(points, "points is null")));
}
private static double computeClusternessMeasure(
SortedMeasurementPoints points) {
if (points.isEmpty()) {
throw new IllegalArgumentException("points is empty");
}
double minimumPoint = points.get(0).doubleValue();
double maximumPoint =
points.get(points.indexOfLastEntry()).doubleValue();
double range = maximumPoint - minimumPoint;
if (range == 0.0) {
// Once here, all data points are equal and so CM must be 1.0.
return 1.0;
}
double expectedDifference = range / points.indexOfLastEntry();
double sum = 0.0;
for (int i = 0; i < points.indexOfLastEntry(); i++) {
double currentDifference =
points.get(i + 1).doubleValue() -
points.get(i).doubleValue();
sum += Math.min(
Math.abs(expectedDifference - currentDifference),
expectedDifference);
}
return sum / range;
}
private static final class SortedMeasurementPoints
implements Iterable<Number> {
private final List<Number> points;
public SortedMeasurementPoints(Collection<Number> points) {
List<Number> processedPoints = new ArrayList<>(points.size());
for (Number point : points) {
if (point == null) {
NullPointerException cause =
new NullPointerException("null points detected");
throw new IllegalArgumentException(cause);
}
processedPoints.add(point);
}
processedPoints.sort(
(a, b) -> Double.compare(
a.doubleValue(),
b.doubleValue()));
this.points = processedPoints;
}
public Number get(int index) {
return points.get(index);
}
public int indexOfLastEntry() {
return points.size() - 1;
}
public boolean isEmpty() {
return points.isEmpty();
}
// For the sake of debugging:
public Iterator<Number> iterator() {
return points.iterator();
}
}
}
```

`com.github.coderodde.codereview.notepad.ClusternessMeasureTest`

```
package com.github.coderodde.codereview.notepad;
import static com.github.coderodde.codereview.notepad.ClusternessMeasure.computeClusternessMeasure;
import java.util.Arrays;
import static junit.framework.Assert.assertEquals;
import org.junit.Test;
/**
* This unit test class tests the
* {@link com.github.coderodde.codereview.notepad.ClusternessMeasure}.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jun 11, 2021)
* @since 1.6 (Jun 11, 2021)
*/
public class ClusternessMeasureTest {
private static final double DELTA = 1e-6;
@Test(expected = NullPointerException.class)
public void throwsOnNullPoints() {
computeClusternessMeasure(null);
}
@Test(expected = IllegalArgumentException.class)
public void throwsOnEmptyPoints() {
computeClusternessMeasure(Arrays.asList());
}
@Test(expected = IllegalArgumentException.class)
public void throwsOnNullPoint() {
computeClusternessMeasure(Arrays.asList(1.0, null, 3.0f));
}
@Test
public void computationOnSinglePoint() {
double measure = computeClusternessMeasure(Arrays.asList(1));
double expected = 1.0;
assertEquals(expected, measure, DELTA);
}
@Test
public void computationOnTwoPoints() {
double measure = computeClusternessMeasure(Arrays.asList(5, 3));
double expected = 0;
assertEquals(expected, measure, DELTA);
}
@Test
public void computeOnThreeEquidistantPoints() {
double measure = computeClusternessMeasure(Arrays.asList(3, 1, 5));
double expected = 0.0;
assertEquals(expected, measure, DELTA);
}
@Test
public void computeOnEqualPoints() {
double measure = computeClusternessMeasure(
Arrays.asList(4, 4f, 4.0, 4));
double expected = 1.0;
assertEquals(expected, measure, DELTA);
}
@Test
public void computeOnSkewedDataPoints() {
double measure = computeClusternessMeasure(Arrays.asList(1, 2.8, 3));
double expected = 0.7999999999999;
assertEquals(expected, measure, DELTA);
}
}
```

**Critique request**

As always, I would be glad to receive any comments.