Anonymous user
Averages/Median: Difference between revisions
→{{header|Java}}
Line 2,094:
{{works with|Java|1.8+}}
This version operates on objects rather than primitives and uses abstractions to operate on all of the standard numerics.
<lang java8>
@FunctionalInterface
interface MedianFinder<T, R> extends Function<Collection<T>, R> {
@
}
@SuppressWarnings("ClassCanBeRecord")
class MedianFinderImpl<T, R> implements MedianFinder<T, R> {
private final Supplier<R> ifEmpty;
private final Function<T, R> ifOdd;
private final Function<List<T>, R> ifEven;
MedianFinderImpl(Supplier<R> ifEmpty, Function<T, R> ifOdd, Function<List<T>, R> ifEven) {
this.ifEmpty = ifEmpty;
this.ifOdd = ifOdd;
this.ifEven = ifEven;
}
@Override
public R apply(Collection<T> data) {
return Objects.requireNonNull(data, "data must not be null").isEmpty()
? ifEven.apply(data.stream().sorted()
.skip(data.size() / 2 - 1)
.limit(2).toList())
: ifOdd.apply(data.stream().sorted()
.skip(data.size() / 2)
.limit(1).findFirst().get());
}
}
private static final MedianFinder<Integer, Integer> INTEGERS = new MedianFinderImpl<>(() -> 0, n -> n, pair -> (pair.get(0) + pair.get(1)) / 2);
private static final MedianFinder<Integer, Float> INTEGERS_AS_FLOAT = new MedianFinderImpl<>(() -> 0f, n -> n * 1f, pair -> (pair.get(0) + pair.get(1)) / 2f);
private static final MedianFinder<Integer, Double> INTEGERS_AS_DOUBLE = new MedianFinderImpl<>(() -> 0d, n -> n * 1d, pair -> (pair.get(0) + pair.get(1)) / 2d);
private static final MedianFinder<Float, Float> FLOATS = new MedianFinderImpl<>(() -> 0f, n -> n, pair -> (pair.get(0) + pair.get(1)) / 2);
private static final MedianFinder<Double, Double> DOUBLES = new MedianFinderImpl<>(() -> 0d, n -> n, pair -> (pair.get(0) + pair.get(1)) / 2);
private static final MedianFinder<BigInteger, BigInteger> BIG_INTEGERS = new MedianFinderImpl<>(() -> BigInteger.ZERO, n -> n, pair -> pair.get(0).add(pair.get(1)).divide(BigInteger.TWO));
private static final MedianFinder<BigInteger, BigDecimal> BIG_INTEGERS_AS_BIG_DECIMAL = new MedianFinderImpl<>(() -> BigDecimal.ZERO, BigDecimal::new, pair -> new BigDecimal(pair.get(0).add(pair.get(1))).divide(BigDecimal.valueOf(2), RoundingMode.FLOOR));
private static final MedianFinder<BigDecimal, BigDecimal> BIG_DECIMALS = new MedianFinderImpl<>(() -> BigDecimal.ZERO, n -> n, pair -> pair.get(0).add(pair.get(1)).divide(BigDecimal.valueOf(2), RoundingMode.FLOOR));
public static Integer integers(Collection<Integer> integerCollection) {
return INTEGERS.apply(integerCollection);
}
public static Float integersAsFloat(Collection<Integer> integerCollection) { return INTEGERS_AS_FLOAT.apply(integerCollection); }
public static Double integersAsDouble(Collection<Integer> integerCollection) { return INTEGERS_AS_DOUBLE.apply(integerCollection); }
public static Float floats(Collection<Float> floatCollection) {
return FLOATS.apply(floatCollection);
}
public static Double doubles(Collection<Double> doubleCollection) {
return DOUBLES.apply(doubleCollection);
}
public static BigInteger bigIntegers(Collection<BigInteger> bigIntegerCollection) { return BIG_INTEGERS.apply(bigIntegerCollection); }
public static BigDecimal bigIntegersAsBigDecimal(Collection<BigInteger> bigIntegerCollection) { return BIG_INTEGERS_AS_BIG_DECIMAL.apply(bigIntegerCollection); }
public static BigDecimal bigDecimals(Collection<BigDecimal> bigDecimalCollection) { return BIG_DECIMALS.apply(bigDecimalCollection); }
}
</lang>
|