From 0d5d262cf4cd9143dd275fc6a2d8ea1b8dd79959 Mon Sep 17 00:00:00 2001 From: Daniel Schramm <xschramm@fi.muni.cz> Date: Mon, 11 Oct 2021 19:08:29 +0200 Subject: [PATCH] Collector for computation of the weighted average implemented --- .../face/WeightedAverageCollector.java | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 Comparison/src/main/java/cz/fidentis/analyst/visitors/face/WeightedAverageCollector.java diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/WeightedAverageCollector.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/WeightedAverageCollector.java new file mode 100644 index 00000000..2ef46945 --- /dev/null +++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/face/WeightedAverageCollector.java @@ -0,0 +1,135 @@ +package cz.fidentis.analyst.visitors.face; + +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.function.ToDoubleFunction; +import java.util.stream.Collector; + +/** + * A collector for computing weighted average suitable for use in Java 8 streams. + * + * <p> + * A mutable reduction operation that accumulates input elements into a mutable + * result container, optionally transforming the accumulated result into a final + * representation after all input elements have been processed. + * </p> + * + * @author Daniel Schramm + * @param <T> Data type of the stream elements + */ +public class WeightedAverageCollector<T> implements Collector<T, IntemediateResults, Double> { + + private final ToDoubleFunction<? super T> valueFunction, weightFunction; + + /** + * Constructor. + * + * @param valueFunction Function returning the value for a given stream element + * @param weightFunction Function returning the weight for a given stream element + */ + public WeightedAverageCollector( + ToDoubleFunction<? super T> valueFunction, + ToDoubleFunction<? super T> weightFunction) { + this.valueFunction = valueFunction; + this.weightFunction = weightFunction; + } + + /** + * Returns a {@link Collector} interface object used to compute the weighted average. + * + * @param <T> Data type of the stream elements + * @param valueFunction Function returning the value for a given stream element + * @param weightFunction Function returning the weight for a given stream element + * @return A Collector interface object used to compute the weighted average + */ + public static <T> Collector<T, ?, Double> toWeightedAverage( + ToDoubleFunction<? super T> valueFunction, + ToDoubleFunction<? super T> weightFunction) { + return new WeightedAverageCollector(valueFunction, weightFunction); + } + + /** + * A function that creates and returns a new mutable result container. + * + * @return A function which returns a new, mutable result container + */ + @Override + public Supplier<IntemediateResults> supplier() { + return IntemediateResults::new; + } + + /** + * A function that folds a value into a mutable result container. + * + * @return A function which folds a value into a mutable result container + */ + @Override + public BiConsumer<IntemediateResults, T> accumulator() { + return (result, streamElement) -> { + result.weightedValSum += valueFunction.applyAsDouble(streamElement) + * weightFunction.applyAsDouble(streamElement); + result.weightSum += weightFunction.applyAsDouble(streamElement); + }; + } + + /** + * A function that accepts two partial results and merges them. The + * combiner function may fold state from one argument into the other and + * return that, or may return a new result container. + * + * @return A function which combines two partial results into a combined + * result + */ + @Override + public BinaryOperator<IntemediateResults> combiner() { + return (result1, result2) -> { + result1.weightedValSum += result2.weightedValSum; + result1.weightSum += result2.weightSum; + + return result1; + }; + } + + /** + * Perform the final transformation from the intermediate accumulation type + * {@code A} to the final result type {@code R}. + * + * <p> + * If the characteristic {@code IDENTITY_FINISH} is + * set, this function may be presumed to be an identity transform with an + * unchecked cast from {@code A} to {@code R}. + * </p> + * + * @return A function which transforms the intermediate result to the final + * result + */ + @Override + public Function<IntemediateResults, Double> finisher() { + return result -> result.weightedValSum / result.weightSum; + } + + /** + * Returns a {@code Set} of {@code Collector.Characteristics} indicating + * the characteristics of this Collector. + * + * @return An immutable set of collector characteristics + */ + @Override + public Set<Characteristics> characteristics() { + return Set.of(Characteristics.UNORDERED); + } +} + +/** + * A helper class which stores intermediate results + * for the {@link WeightedAverageCollector} class. + * + * @author Daniel Schramm + */ +class IntemediateResults { + double weightedValSum = 0; + double weightSum = 0; +} -- GitLab