Class Quantile

  • All Implemented Interfaces:
    DoubleConsumer

    public class Quantile
    extends Object
    implements DoubleConsumer
    Implementation of the quantile estimation algorithm published by

    Raj JAIN and Imrich CHLAMTAC: The P2 Algorithm for Dynamic Calculation of Quantiles and Histograms Without Storing Observations
    [Communications of the ACM; October 1985, Volume 28, Number 10]

    This class is designed to work with (though does not require) streams. For example, you can compute the quantile with:

    final DoubleStream stream = ... final Quantile quantile = stream.collect( () -> new Quantile(0.23), Quantile::accept, Quantile::combine );
    Since:
    1.0
    Version:
    6.0
    See Also:
    Wikipedia: Quantile
    Implementation Note:
    This implementation is not thread safe. However, it is safe to use on a parallel stream, because the parallel implementation of Stream.collect() provides the necessary partitioning, isolation, and merging of results for safe and efficient parallel execution. Using this class in the collect method of an parallel stream can lead to an reduced accuracy of the quantile value. Since this implementation is an estimation algorithm, combining the estimations will only work for large streams (size >> 1000).
    • Constructor Detail

      • Quantile

        public Quantile​(double quantile)
        Create a new quantile accumulator with the given value.
        Parameters:
        quantile - the wished quantile value.
        Throws:
        IllegalArgumentException - if the quantile is not in the range [0, 1].
    • Method Detail

      • reset

        public void reset()
        Reset this object to its initial state.
      • quantile

        public double quantile()
        Return the quantile this object has been parametrized with.
        Returns:
        the quantile this object has been parametrized with
        Since:
        3.1
      • value

        public double value()
        Return the computed quantile value.
        Returns:
        the quantile value.
      • count

        public long count()
        Return the number of samples the quantile value was calculated of.
        Returns:
        the number of samples the quantile value was calculated of
      • sameState

        public boolean sameState​(Quantile other)
        Compares the state of two Quantile objects. This is a replacement for the Object.equals(Object) which is not advisable to implement for this mutable object. If two object have the same state, it has still the same state when updated with the same value.
        final Quantile q1 = ...; final Quantile q2 = ...; if (q1.sameState(q2)) { final double value = random.nextDouble(); q1.accept(value); q2.accept(value); assert q1.sameState(q2); assert q2.sameState(q1); assert q1.sameState(q1); }
        Parameters:
        other - the other object for the test
        Returns:
        true the this and the other objects have the same state, false otherwise
        Since:
        3.7
      • toQuantile

        public static <T> Collector<T,​?,​QuantiletoQuantile​(double quantile,
                                                                         ToDoubleFunction<? super T> mapper)
        Return a Collector which applies an double-producing mapping function to each input element, and returns quantiles for the resulting values.
        final Stream<SomeObject> stream = ... final Quantile quantile = stream .collect(toQuantile(0.25, v -> v.doubleValue()));
        Type Parameters:
        T - the type of the input elements
        Parameters:
        quantile - the wished quantile value.
        mapper - a mapping function to apply to each element
        Returns:
        a Collector implementing the quantiles reduction
        Throws:
        NullPointerException - if the given mapper is null
        IllegalArgumentException - if the quantile is not in the range [0, 1].
      • toMedian

        public static <T> Collector<T,​?,​QuantiletoMedian​(ToDoubleFunction<? super T> mapper)
        Return a Collector which applies an double-producing mapping function to each input element, and returns the median for the resulting values.
        final Stream<SomeObject> stream = ... final Quantile median = stream.collect(toMedian(v -> v.doubleValue()));
        Type Parameters:
        T - the type of the input elements
        Parameters:
        mapper - a mapping function to apply to each element
        Returns:
        a Collector implementing the quantiles reduction
        Throws:
        NullPointerException - if the given mapper is null