IntSummary.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-5.2.0).
003  * Copyright (c) 2007-2020 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 import static io.jenetics.internal.util.Hashes.hash;
025 
026 import java.io.Serializable;
027 import java.util.IntSummaryStatistics;
028 import java.util.function.ToIntFunction;
029 import java.util.stream.Collector;
030 
031 /**
032  <i>Value</i> objects which contains statistical summary information.
033  *
034  @see java.util.IntSummaryStatistics
035  *
036  * @implNote
037  * This class is immutable and thread-safe.
038  *
039  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
040  @since 3.0
041  @version 5.2
042  */
043 public final /*record*/ class IntSummary implements Serializable {
044 
045     private static final long serialVersionUID = 1L;
046 
047     private final long _count;
048     private final int _min;
049     private final int _max;
050     private final long _sum;
051     private final double _mean;
052 
053     /**
054      * Create an immutable object which contains statistical summary values.
055      *
056      @param count the count of values recorded
057      @param min the minimum value
058      @param max the maximum value
059      @param sum the sum of the recorded values
060      @param mean the arithmetic mean of values
061      */
062     private IntSummary(
063         final long count,
064         final int min,
065         final int max,
066         final long sum,
067         final double mean
068     ) {
069         _count = count;
070         _min = min;
071         _max = max;
072         _sum = sum;
073         _mean = mean;
074     }
075 
076     /**
077      * Returns the count of values recorded.
078      *
079      @return the count of recorded values
080      */
081     public long count() {
082         return _count;
083     }
084 
085     /**
086      * Returns the count of values recorded.
087      *
088      @return the count of recorded values
089      @deprecated Use {@link #count()} instead
090      */
091     @Deprecated
092     public long getCount() {
093         return _count;
094     }
095 
096     /**
097      * Return the minimum value recorded, or {@code Integer.MAX_VALUE} if no
098      * values have been recorded.
099      *
100      @return the minimum value, or {@code Integer.MAX_VALUE} if none
101      */
102     public int min() {
103         return _min;
104     }
105 
106     /**
107      * Return the minimum value recorded, or {@code Integer.MAX_VALUE} if no
108      * values have been recorded.
109      *
110      @return the minimum value, or {@code Integer.MAX_VALUE} if none
111      @deprecated Use {@link #min()} instead
112      */
113     @Deprecated
114     public int getMin() {
115         return _min;
116     }
117 
118     /**
119      * Return the maximum value recorded, or {@code Integer.MIN_VALUE} if no
120      * values have been recorded.
121      *
122      @return the maximum value, or {@code Integer.MIN_VALUE} if none
123      */
124     public int max() {
125         return _max;
126     }
127 
128     /**
129      * Return the maximum value recorded, or {@code Integer.MIN_VALUE} if no
130      * values have been recorded.
131      *
132      @return the maximum value, or {@code Integer.MIN_VALUE} if none
133      @deprecated Use {@link #max()} instead
134      */
135     @Deprecated
136     public int getMax() {
137         return _max;
138     }
139 
140     /**
141      * Return the sum of values recorded, or zero if no values have been
142      * recorded.
143      *
144      @return the sum of values, or zero if none
145      */
146     public long sum() {
147         return _sum;
148     }
149 
150     /**
151      * Return the sum of values recorded, or zero if no values have been
152      * recorded.
153      *
154      @return the sum of values, or zero if none
155      @deprecated Use {@link #sum()} instead
156      */
157     @Deprecated
158     public long getSum() {
159         return _sum;
160     }
161 
162     /**
163      * Return the arithmetic mean of values recorded, or zero if no values have
164      * been recorded.
165      *
166      @return the arithmetic mean of values, or zero if none
167      */
168     public double mean() {
169         return _mean;
170     }
171 
172     /**
173      * Return the arithmetic mean of values recorded, or zero if no values have
174      * been recorded.
175      *
176      @return the arithmetic mean of values, or zero if none
177      @deprecated Use {@link #mean()} instead
178      */
179     @Deprecated
180     public double getMean() {
181         return _mean;
182     }
183 
184     @Override
185     public int hashCode() {
186         return
187             hash(_count,
188             hash(_sum,
189             hash(_min,
190             hash(_max,
191             hash(_mean)))));
192     }
193 
194     @Override
195     public boolean equals(final Object obj) {
196         return obj == this ||
197             obj instanceof IntSummary &&
198             _count == ((IntSummary)obj)._count &&
199             _sum == ((IntSummary)obj)._sum &&
200             _min == ((IntSummary)obj)._min &&
201             _max == ((IntSummary)obj)._max &&
202             Double.compare(_mean, ((IntSummary)obj)._mean== 0;
203     }
204 
205     @Override
206     public String toString() {
207         return String.format(
208             "IntSummary[N=%d, ∧=%s, ∨=%s, Σ=%s, μ=%s]",
209             count(), min(), max(), sum(), mean()
210         );
211     }
212 
213     /**
214      * Create an immutable object which contains statistical summary values.
215      *
216      @param count the count of values recorded
217      @param min the minimum value
218      @param max the maximum value
219      @param sum the sum of the recorded values
220      @param mean the arithmetic mean of values
221      @return an immutable object which contains statistical values
222      */
223     public static IntSummary of(
224         final long count,
225         final int min,
226         final int max,
227         final long sum,
228         final double mean
229     ) {
230         return new IntSummary(
231             count,
232             min,
233             max,
234             sum,
235             mean
236         );
237     }
238 
239     /**
240      * Return a new value object of the statistical summary, currently
241      * represented by the {@code statistics} object.
242      *
243      @param statistics the creating (mutable) statistics class
244      @return the statistical moments
245      */
246     public static IntSummary of(final IntSummaryStatistics statistics) {
247         return new IntSummary(
248             statistics.getCount(),
249             statistics.getMin(),
250             statistics.getMax(),
251             statistics.getSum(),
252             statistics.getAverage()
253         );
254     }
255 
256     /**
257      * Return a {@code Collector} which applies an int-producing mapping
258      * function to each input element, and returns summary-statistics for the
259      * resulting values.
260      *
261      <pre>{@code
262      * final Stream<SomeObject> stream = ...
263      * final IntSummary summary = stream
264      *     .collect(toIntSummary(v -> v.intValue()));
265      * }</pre>
266      *
267      @param mapper a mapping function to apply to each element
268      @param <T> the type of the input elements
269      @return a {@code Collector} implementing the summary-statistics reduction
270      @throws java.lang.NullPointerException if the given {@code mapper} is
271      *         {@code null}
272      */
273     public static <T> Collector<T, ?, IntSummary>
274     toIntSummary(final ToIntFunction<? super T> mapper) {
275         requireNonNull(mapper);
276         return Collector.of(
277             IntSummaryStatistics::new,
278             (a, b-> a.accept(mapper.applyAsInt(b)),
279             (a, b-> {a.combine(b)return a;},
280             IntSummary::of
281         );
282     }
283 
284 
285     /* *************************************************************************
286      * Some static helper methods.
287      **************************************************************************/
288 
289     /**
290      * Return the minimum value of the given double array.
291      *
292      @since 4.0
293      *
294      @param values the array.
295      @return the minimum value or {@link Integer#MAX_VALUE} if the given array is
296      *         empty.
297      @throws NullPointerException if the given array is {@code null}.
298      */
299     public static int min(final int[] values) {
300         int min = Integer.MAX_VALUE;
301         if (values.length > 0) {
302             min = values[0];
303             for (int value : values) {
304                 if (value < min) {
305                     min = value;
306                 }
307             }
308         }
309 
310         return min;
311     }
312 
313     /**
314      * Return the maximum value of the given double array.
315      *
316      @since 4.0
317      *
318      @param values the array.
319      @return the maximum value or {@link Integer#MIN_VALUE} if the given array is
320      *         empty.
321      @throws NullPointerException if the given array is {@code null}.
322      */
323     public static int max(final int[] values) {
324         int max = Integer.MIN_VALUE;
325         if (values.length > 0) {
326             max = values[0];
327             for (int value : values) {
328                 if (value > max) {
329                     max = value;
330                 }
331             }
332         }
333 
334         return max;
335     }
336 
337     /**
338      * Return the sum of the given double array.
339      *
340      @since 4.0
341      *
342      @param values the values to sum up.
343      @return the sum of the given {@code values}.
344      @throws NullPointerException if the given array is {@code null}.
345      */
346     public static long sum(final int[] values) {
347         long sum = 0;
348         for (int i = values.length; --i >= 0;) {
349             sum += values[i];
350         }
351         return sum;
352     }
353 
354     /**
355      * Returns a double describing the arithmetic mean of the values, or
356      {@link Double#NaN} if the {@code values} array is empty.
357      *
358      @since 4.0
359      *
360      @param values the values to calculate the mean of
361      @return the arithmetic mean of the given {@code values} or
362      *         {@link Double#NaN} if the {@code values} array is empty
363      @throws NullPointerException if the given array is {@code null}.
364      */
365     public static double mean(final int[] values) {
366         return values.length > (double)sum(values)/values.length : NaN;
367     }
368 
369 }