FStat implements IQualityMeasure { @Override public double assessQuality(final List<Double> distances, final int[] classValues) { HashMap<Integer, List<Double>> classDistances = new HashMap<>(); for (int i = 0; i < distances.size(); i++) { if (!classDistances.containsKey(classValues[i])) { classDistances.put(classValues[i], new ArrayList<>()); } classDistances.get(classValues[i]).add(distances.get(i)); } int numClasses = classDistances.size(); HashMap<Integer, Double> classMeans = new HashMap<>(); for (Entry<Integer, List<Double>> entry : classDistances.entrySet()) { Integer clazz = entry.getKey(); classMeans.put(clazz, entry.getValue().stream().mapToDouble(a -> a).average().getAsDouble()); } double completeMean = distances.stream().mapToDouble(a -> a).average().getAsDouble(); double denominator = 0; double result = 0; for (Entry<Integer, Double> entry : classMeans.entrySet()) { Integer clazz = entry.getKey(); double mean = entry.getValue(); result += Math.pow(mean - completeMean, 2); for (Double dist : classDistances.get(clazz)) { denominator += Math.pow(dist - mean, 2); } } result /= numClasses - 1; denominator /= distances.size() - numClasses; if (denominator == 0) { throw new IllegalArgumentException("Given arguments yield a 0 " + denominator); } result /= denominator; return result; }  @Override double assessQuality(final List<Double> distances, final int[] classValues);  }
@Test public void assessQualityTest() { FStat fStat = new FStat(); List<Double> distances = Arrays.asList(2d, 4d, 3d); int[] classValues = new int[] { 0, 0, 1 }; Assert.assertEquals(0, fStat.assessQuality(distances, classValues), EPS_DELTA); distances = Arrays.asList(1d, 4d, 3d); classValues = new int[] { 0, 0, 1 }; Assert.assertEquals((5d / 36d) / (9d / 2d), fStat.assessQuality(distances, classValues), EPS_DELTA); }