149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera/*
249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *
549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * This code is free software; you can redistribute it and/or modify it
649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * under the terms of the GNU General Public License version 2 only, as
749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * published by the Free Software Foundation.  Oracle designates this
849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * particular file as subject to the "Classpath" exception as provided
949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * by Oracle in the LICENSE file that accompanied this code.
1049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *
1149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * This code is distributed in the hope that it will be useful, but WITHOUT
1249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * version 2 for more details (a copy is included in the LICENSE file that
1549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * accompanied this code).
1649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *
1749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * You should have received a copy of the GNU General Public License version
1849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * 2 along with this work; if not, write to the Free Software Foundation,
1949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *
2149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * or visit www.oracle.com if you need additional information or have any
2349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * questions.
2449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera */
2549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmerapackage java.util;
2649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
2749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmeraimport java.util.function.IntConsumer;
2849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
2949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera/**
3049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * A state object for collecting statistics such as count, min, max, sum, and
3149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * average.
3249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *
3349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * <p>This class is designed to work with (though does not require)
34a2f3a30b4256145b4317bf4b14f6d838906d8c8fShubham Ajmera * {@linkplain java.util.stream streams}. For example, you can compute
3549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * summary statistics on a stream of ints with:
3649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * <pre> {@code
3749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * IntSummaryStatistics stats = intStream.collect(IntSummaryStatistics::new,
3849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *                                                IntSummaryStatistics::accept,
3949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *                                                IntSummaryStatistics::combine);
4049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * }</pre>
4149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *
4249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * <p>{@code IntSummaryStatistics} can be used as a
43a2f3a30b4256145b4317bf4b14f6d838906d8c8fShubham Ajmera * {@linkplain java.util.stream.Stream#collect(Collector) reduction}
44a2f3a30b4256145b4317bf4b14f6d838906d8c8fShubham Ajmera * target for a {@linkplain java.util.stream.Stream stream}. For example:
4549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *
4649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * <pre> {@code
4749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * IntSummaryStatistics stats = people.stream()
4849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *                                    .collect(Collectors.summarizingInt(Person::getDependents));
4949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *}</pre>
5049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *
5149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * This computes, in a single pass, the count of people, as well as the minimum,
5249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * maximum, sum, and average of their number of dependents.
5349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *
5449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * @implNote This implementation is not thread safe. However, it is safe to use
55a2f3a30b4256145b4317bf4b14f6d838906d8c8fShubham Ajmera * {@link java.util.stream.Collectors#summarizingInt(java.util.function.ToIntFunction)
5649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * Collectors.toIntStatistics()} on a parallel stream, because the parallel
57a2f3a30b4256145b4317bf4b14f6d838906d8c8fShubham Ajmera * implementation of {@link java.util.stream.Stream#collect Stream.collect()}
5849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * provides the necessary partitioning, isolation, and merging of results for
5949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * safe and efficient parallel execution.
6049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera *
6149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * <p>This implementation does not check for overflow of the sum.
6249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera * @since 1.8
6349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera */
6449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmerapublic class IntSummaryStatistics implements IntConsumer {
6549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    private long count;
6649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    private long sum;
6749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    private int min = Integer.MAX_VALUE;
6849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    private int max = Integer.MIN_VALUE;
6949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
7049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    /**
7149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * Construct an empty instance with zero count, zero sum,
7249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero
7349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * average.
7449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     */
7549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    public IntSummaryStatistics() { }
7649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
7749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    /**
7849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * Records a new value into the summary information
7949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     *
8049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * @param value the input value
8149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     */
8249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    @Override
8349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    public void accept(int value) {
8449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        ++count;
8549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        sum += value;
8649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        min = Math.min(min, value);
8749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        max = Math.max(max, value);
8849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    }
8949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
9049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    /**
9149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * Combines the state of another {@code IntSummaryStatistics} into this one.
9249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     *
9349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * @param other another {@code IntSummaryStatistics}
9449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * @throws NullPointerException if {@code other} is null
9549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     */
9649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    public void combine(IntSummaryStatistics other) {
9749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        count += other.count;
9849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        sum += other.sum;
9949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        min = Math.min(min, other.min);
10049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        max = Math.max(max, other.max);
10149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    }
10249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
10349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    /**
10449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * Returns the count of values recorded.
10549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     *
10649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * @return the count of values
10749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     */
10849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    public final long getCount() {
10949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        return count;
11049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    }
11149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
11249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    /**
11349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * Returns the sum of values recorded, or zero if no values have been
11449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * recorded.
11549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     *
11649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * @return the sum of values, or zero if none
11749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     */
11849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    public final long getSum() {
11949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        return sum;
12049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    }
12149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
12249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    /**
12349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * Returns the minimum value recorded, or {@code Integer.MAX_VALUE} if no
12449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * values have been recorded.
12549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     *
12649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * @return the minimum value, or {@code Integer.MAX_VALUE} if none
12749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     */
12849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    public final int getMin() {
12949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        return min;
13049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    }
13149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
13249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    /**
13349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * Returns the maximum value recorded, or {@code Integer.MIN_VALUE} if no
13449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * values have been recorded.
13549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     *
13649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * @return the maximum value, or {@code Integer.MIN_VALUE} if none
13749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     */
13849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    public final int getMax() {
13949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        return max;
14049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    }
14149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
14249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    /**
14349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * Returns the arithmetic mean of values recorded, or zero if no values have been
14449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * recorded.
14549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     *
14649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * @return the arithmetic mean of values, or zero if none
14749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     */
14849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    public final double getAverage() {
14949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
15049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    }
15149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera
15249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    @Override
15349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    /**
15449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * {@inheritDoc}
15549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     *
15649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * Returns a non-empty string representation of this object suitable for
15749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * debugging. The exact presentation format is unspecified and may vary
15849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     * between implementations and versions.
15949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera     */
16049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    public String toString() {
16149b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera        return String.format(
16249b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera            "%s{count=%d, sum=%d, min=%d, average=%f, max=%d}",
16349b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera            this.getClass().getSimpleName(),
16449b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera            getCount(),
16549b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera            getSum(),
16649b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera            getMin(),
16749b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera            getAverage(),
16849b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera            getMax());
16949b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera    }
17049b5e20d6e5c17985c141fff49f135b05284b62dShubham Ajmera}
171