All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ethelred.util.stream.SummaryStatistics Maven / Gradle / Ivy

The newest version!
/* (C) 2024 */
package org.ethelred.util.stream;

import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Collector;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

/**
 * A stream Collector that captures basic statistics in a single result. Currently, count, max and min.
 */
@NullMarked
public class SummaryStatistics {
    private final Comparator comparator;
    private int count;

    @Nullable private T min;

    @Nullable private T max;

    private SummaryStatistics(Comparator comparator) {
        this.comparator = comparator;
    }

    /**
     * A Collector that uses the natural order to determine max and min.
     * @return Collector producing SummaryStatistics.
     * @param  The type of elements in the Stream
     */
    public static > Collector> collector() {
        return collector(Comparator.naturalOrder());
    }

    /**
     * A Collector that uses an explicit Comparator to determine max and min.
     * @param comparator Ordering to use
     * @return Collector producing SummaryStatistics.
     * @param  The type of elements in the Stream
     */
    public static  Collector> collector(Comparator comparator) {
        return Collector.of(
                () -> new SummaryStatistics<>(comparator), SummaryStatistics::add, SummaryStatistics::combine);
    }

    private void add(T t) {
        count++;
        _min(t);
        _max(t);
    }

    private void _max(@Nullable T t) {
        if (t == null) {
            return;
        }
        if (max == null || comparator.compare(t, max) > 0) {
            max = t;
        }
    }

    private void _min(@Nullable T t) {
        if (t == null) {
            return;
        }
        if (min == null || comparator.compare(t, min) < 0) {
            min = t;
        }
    }

    private SummaryStatistics combine(SummaryStatistics other) {
        count += other.count;
        _min(other.min);
        _max(other.max);
        return this;
    }

    /**
     *
     * @return The minimum valued element from the Stream. Empty if the Stream was empty.
     */
    public Optional getMin() {
        return Optional.ofNullable(min);
    }

    /**
     *
     * @return The maximum valued element from the Stream. Empty if the Stream was empty.
     */
    public Optional getMax() {
        return Optional.ofNullable(max);
    }

    /**
     *
     * @return Count of elements from the Stream
     */
    public int getCount() {
        return count;
    }
}