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