IntSummary.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-4.1.0).
003  * Copyright (c) 2007-2018 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019  */
020 package io.jenetics.stat;
021 
022 import static java.lang.Double.NaN;
023 import static java.util.Objects.requireNonNull;
024 
025 import java.io.Serializable;
026 import java.util.IntSummaryStatistics;
027 import java.util.function.ToIntFunction;
028 import java.util.stream.Collector;
029 
030 /**
031  <i>Value</i> objects which contains statistical summary information.
032  *
033  @see java.util.IntSummaryStatistics
034  *
035  * @implSpec
036  * This class is immutable and thread-safe.
037  *
038  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
039  @since 3.0
040  @version 3.0
041  */
042 public final class IntSummary implements Serializable {
043 
044     private static final long serialVersionUID = 1L;
045 
046     private final long _count;
047     private final int _min;
048     private final int _max;
049     private final long _sum;
050     private final double _mean;
051 
052     /**
053      * Create an immutable object which contains statistical summary values.
054      *
055      @param count the count of values recorded
056      @param min the minimum value
057      @param max the maximum value
058      @param sum the sum of the recorded values
059      @param mean the arithmetic mean of values
060      */
061     private IntSummary(
062         final long count,
063         final int min,
064         final int max,
065         final long sum,
066         final double mean
067     ) {
068         _count = count;
069         _min = min;
070         _max = max;
071         _sum = sum;
072         _mean = mean;
073     }
074 
075     /**
076      * Returns the count of values recorded.
077      *
078      @return the count of recorded values
079      */
080     public long getCount() {
081         return _count;
082     }
083 
084     /**
085      * Return the minimum value recorded, or {@code Integer.MAX_VALUE} if no
086      * values have been recorded.
087      *
088      @return the minimum value, or {@code Integer.MAX_VALUE} if none
089      */
090     public int getMin() {
091         return _min;
092     }
093 
094     /**
095      * Return the maximum value recorded, or {@code Integer.MIN_VALUE} if no
096      * values have been recorded.
097      *
098      @return the maximum value, or {@code Integer.MIN_VALUE} if none
099      */
100     public int getMax() {
101         return _max;
102     }
103 
104     /**
105      * Return the sum of values recorded, or zero if no values have been
106      * recorded.
107      *
108      @return the sum of values, or zero if none
109      */
110     public long getSum() {
111         return _sum;
112     }
113 
114     /**
115      * Return the arithmetic mean of values recorded, or zero if no values have
116      * been recorded.
117      *
118      @return the arithmetic mean of values, or zero if none
119      */
120     public double getMean() {
121         return _mean;
122     }
123 
124     @Override
125     public int hashCode() {
126         int hash = 17;
127         hash += 33*_count + 37;
128         hash += 33*_sum + 37;
129         hash += 33*_min + 37;
130         hash += 33*_max + 37;
131         hash += 33*Double.hashCode(_mean37;
132         return hash;
133     }
134 
135     @Override
136     public boolean equals(final Object obj) {
137         return obj == this ||
138             obj instanceof IntSummary &&
139             _count == ((IntSummary)obj)._count &&
140             _sum == ((IntSummary)obj)._sum &&
141             _min == ((IntSummary)obj)._min &&
142             _max == ((IntSummary)obj)._max &&
143             Double.compare(_mean, ((IntSummary)obj)._mean== 0;
144     }
145 
146     @Override
147     public String toString() {
148         return String.format(
149             "IntSummary[N=%d, ∧=%s, ∨=%s, Σ=%s, μ=%s]",
150             getCount(), getMin(), getMax(), getSum(), getMean()
151         );
152     }
153 
154     /**
155      * Create an immutable object which contains statistical summary values.
156      *
157      @param count the count of values recorded
158      @param min the minimum value
159      @param max the maximum value
160      @param sum the sum of the recorded values
161      @param mean the arithmetic mean of values
162      @return an immutable object which contains statistical values
163      */
164     public static IntSummary of(
165         final long count,
166         final int min,
167         final int max,
168         final long sum,
169         final double mean
170     ) {
171         return new IntSummary(
172             count,
173             min,
174             max,
175             sum,
176             mean
177         );
178     }
179 
180     /**
181      * Return a new value object of the statistical summary, currently
182      * represented by the {@code statistics} object.
183      *
184      @param statistics the creating (mutable) statistics class
185      @return the statistical moments
186      */
187     public static IntSummary of(final IntSummaryStatistics statistics) {
188         return new IntSummary(
189             statistics.getCount(),
190             statistics.getMin(),
191             statistics.getMax(),
192             statistics.getSum(),
193             statistics.getAverage()
194         );
195     }
196 
197     /**
198      * Return a {@code Collector} which applies an int-producing mapping
199      * function to each input element, and returns summary-statistics for the
200      * resulting values.
201      *
202      <pre>{@code
203      * final Stream<SomeObject> stream = ...
204      * final IntSummary summary = stream
205      *     .collect(toIntSummary(v -> v.intValue()));
206      * }</pre>
207      *
208      @param mapper a mapping function to apply to each element
209      @param <T> the type of the input elements
210      @return a {@code Collector} implementing the summary-statistics reduction
211      @throws java.lang.NullPointerException if the given {@code mapper} is
212      *         {@code null}
213      */
214     public static <T> Collector<T, ?, IntSummary>
215     toIntSummary(final ToIntFunction<? super T> mapper) {
216         requireNonNull(mapper);
217         return Collector.of(
218             IntSummaryStatistics::new,
219             (a, b-> a.accept(mapper.applyAsInt(b)),
220             (a, b-> {a.combine(b)return a;},
221             IntSummary::of
222         );
223     }
224 
225 
226     /* *************************************************************************
227      * Some static helper methods.
228      **************************************************************************/
229 
230     /**
231      * Return the minimum value of the given double array.
232      *
233      @since 4.0
234      *
235      @param values the array.
236      @return the minimum value or {@link Integer#MAX_VALUE} if the given array is
237      *         empty.
238      @throws NullPointerException if the given array is {@code null}.
239      */
240     public static int min(final int[] values) {
241         int min = Integer.MAX_VALUE;
242         if (values.length > 0) {
243             min = values[0];
244 
245             for (int i = 0; i < values.length; ++i) {
246                 if (values[i< min) {
247                     min = values[i];
248                 }
249             }
250         }
251 
252         return min;
253     }
254 
255     /**
256      * Return the maximum value of the given double array.
257      *
258      @since 4.0
259      *
260      @param values the array.
261      @return the maximum value or {@link Integer#MIN_VALUE} if the given array is
262      *         empty.
263      @throws NullPointerException if the given array is {@code null}.
264      */
265     public static int max(final int[] values) {
266         int max = Integer.MIN_VALUE;
267         if (values.length > 0) {
268             max = values[0];
269 
270             for (int i = 0; i < values.length; ++i) {
271                 if (values[i> max) {
272                     max = values[i];
273                 }
274             }
275         }
276 
277         return max;
278     }
279 
280     /**
281      * Return the sum of the given double array.
282      *
283      @since 4.0
284      *
285      @param values the values to sum up.
286      @return the sum of the given {@code values}.
287      @throws NullPointerException if the given array is {@code null}.
288      */
289     public static long sum(final int[] values) {
290         long sum = 0;
291         for (int i = values.length; --i >= 0;) {
292             sum += values[i];
293         }
294         return sum;
295     }
296 
297     /**
298      * Returns a double describing the arithmetic mean of the values, or
299      {@link Double#NaN} if the {@code values} array is empty.
300      *
301      @since 4.0
302      *
303      @param values the values to calculate the mean of
304      @return the arithmetic mean of the given {@code values} or
305      *         {@link Double#NaN} if the {@code values} array is empty
306      @throws NullPointerException if the given array is {@code null}.
307      */
308     public static double mean(final int[] values) {
309         return values.length > (double)sum(values)/values.length : NaN;
310     }
311 
312 }