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 > 0 ? (double)sum(values)/values.length : NaN;
367 }
368
369 }
|