1 /*
2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package java.util;
26 
27 import java.util.function.IntConsumer;
28 
29 /**
30  * A state object for collecting statistics such as count, min, max, sum, and
31  * average.
32  *
33  * <p>This class is designed to work with (though does not require)
34  * {@linkplain java.util.stream streams}. For example, you can compute
35  * summary statistics on a stream of ints with:
36  * <pre> {@code
37  * IntSummaryStatistics stats = intStream.collect(IntSummaryStatistics::new,
38  *                                                IntSummaryStatistics::accept,
39  *                                                IntSummaryStatistics::combine);
40  * }</pre>
41  *
42  * <p>{@code IntSummaryStatistics} can be used as a
43  * {@linkplain java.util.stream.Stream#collect(Collector) reduction}
44  * target for a {@linkplain java.util.stream.Stream stream}. For example:
45  *
46  * <pre> {@code
47  * IntSummaryStatistics stats = people.stream()
48  *                                    .collect(Collectors.summarizingInt(Person::getDependents));
49  *}</pre>
50  *
51  * This computes, in a single pass, the count of people, as well as the minimum,
52  * maximum, sum, and average of their number of dependents.
53  *
54  * @implNote This implementation is not thread safe. However, it is safe to use
55  * {@link java.util.stream.Collectors#summarizingInt(java.util.function.ToIntFunction)
56  * Collectors.toIntStatistics()} on a parallel stream, because the parallel
57  * implementation of {@link java.util.stream.Stream#collect Stream.collect()}
58  * provides the necessary partitioning, isolation, and merging of results for
59  * safe and efficient parallel execution.
60  *
61  * <p>This implementation does not check for overflow of the sum.
62  * @since 1.8
63  */
64 public class IntSummaryStatistics implements IntConsumer {
65     private long count;
66     private long sum;
67     private int min = Integer.MAX_VALUE;
68     private int max = Integer.MIN_VALUE;
69 
70     /**
71      * Construct an empty instance with zero count, zero sum,
72      * {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero
73      * average.
74      */
IntSummaryStatistics()75     public IntSummaryStatistics() { }
76 
77     /**
78      * Records a new value into the summary information
79      *
80      * @param value the input value
81      */
82     @Override
accept(int value)83     public void accept(int value) {
84         ++count;
85         sum += value;
86         min = Math.min(min, value);
87         max = Math.max(max, value);
88     }
89 
90     /**
91      * Combines the state of another {@code IntSummaryStatistics} into this one.
92      *
93      * @param other another {@code IntSummaryStatistics}
94      * @throws NullPointerException if {@code other} is null
95      */
combine(IntSummaryStatistics other)96     public void combine(IntSummaryStatistics other) {
97         count += other.count;
98         sum += other.sum;
99         min = Math.min(min, other.min);
100         max = Math.max(max, other.max);
101     }
102 
103     /**
104      * Returns the count of values recorded.
105      *
106      * @return the count of values
107      */
getCount()108     public final long getCount() {
109         return count;
110     }
111 
112     /**
113      * Returns the sum of values recorded, or zero if no values have been
114      * recorded.
115      *
116      * @return the sum of values, or zero if none
117      */
getSum()118     public final long getSum() {
119         return sum;
120     }
121 
122     /**
123      * Returns the minimum value recorded, or {@code Integer.MAX_VALUE} if no
124      * values have been recorded.
125      *
126      * @return the minimum value, or {@code Integer.MAX_VALUE} if none
127      */
getMin()128     public final int getMin() {
129         return min;
130     }
131 
132     /**
133      * Returns the maximum value recorded, or {@code Integer.MIN_VALUE} if no
134      * values have been recorded.
135      *
136      * @return the maximum value, or {@code Integer.MIN_VALUE} if none
137      */
getMax()138     public final int getMax() {
139         return max;
140     }
141 
142     /**
143      * Returns the arithmetic mean of values recorded, or zero if no values have been
144      * recorded.
145      *
146      * @return the arithmetic mean of values, or zero if none
147      */
getAverage()148     public final double getAverage() {
149         return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
150     }
151 
152     @Override
153     /**
154      * {@inheritDoc}
155      *
156      * Returns a non-empty string representation of this object suitable for
157      * debugging. The exact presentation format is unspecified and may vary
158      * between implementations and versions.
159      */
toString()160     public String toString() {
161         return String.format(
162             "%s{count=%d, sum=%d, min=%d, average=%f, max=%d}",
163             this.getClass().getSimpleName(),
164             getCount(),
165             getSum(),
166             getMin(),
167             getAverage(),
168             getMax());
169     }
170 }
171