LongSummary.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-4.3.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 import static io.jenetics.internal.util.Hashes.hash;
025 
026 import java.io.Serializable;
027 import java.util.LongSummaryStatistics;
028 import java.util.function.ToLongFunction;
029 import java.util.stream.Collector;
030 
031 /**
032  <i>Value</i> objects which contains statistical summary information.
033  *
034  @see java.util.LongSummaryStatistics
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 3.0
042  */
043 public final class LongSummary implements Serializable {
044 
045     private static final long serialVersionUID = 1L;
046 
047     private final long _count;
048     private final long _min;
049     private final long _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 LongSummary(
063         final long count,
064         final long min,
065         final long 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 getCount() {
082         return _count;
083     }
084 
085     /**
086      * Return the minimum value recorded, or {@code Long.MAX_VALUE} if no
087      * values have been recorded.
088      *
089      @return the minimum value, or {@code Long.MAX_VALUE} if none
090      */
091     public long getMin() {
092         return _min;
093     }
094 
095     /**
096      * Return the maximum value recorded, or {@code Long.MIN_VALUE} if no
097      * values have been recorded.
098      *
099      @return the maximum value, or {@code Long.MIN_VALUE} if none
100      */
101     public long getMax() {
102         return _max;
103     }
104 
105     /**
106      * Return the sum of values recorded, or zero if no values have been
107      * recorded.
108      *
109      @return the sum of values, or zero if none
110      */
111     public long getSum() {
112         return _sum;
113     }
114 
115     /**
116      * Return the arithmetic mean of values recorded, or zero if no values have
117      * been recorded.
118      *
119      @return the arithmetic mean of values, or zero if none
120      */
121     public double getMean() {
122         return _mean;
123     }
124 
125     @Override
126     public int hashCode() {
127         return
128             hash(_count,
129             hash(_sum,
130             hash(_min,
131             hash(_max,
132             hash(_mean,
133             hash(getClass()))))));
134     }
135 
136     @Override
137     public boolean equals(final Object obj) {
138         return obj == this ||
139             obj instanceof LongSummary &&
140             _count == ((LongSummary)obj)._count &&
141             _sum == ((LongSummary)obj)._sum &&
142             _min == ((LongSummary)obj)._min &&
143             _max == ((LongSummary)obj)._max &&
144             Double.compare(_mean, ((LongSummary)obj)._mean== 0;
145     }
146 
147     @Override
148     public String toString() {
149         return String.format(
150             "LongSummary[N=%d, ∧=%s, ∨=%s, Σ=%s, μ=%s]",
151             getCount(), getMin(), getMax(), getSum(), getMean()
152         );
153     }
154 
155     /**
156      * Create an immutable object which contains statistical summary values.
157      *
158      @param count the count of values recorded
159      @param min the minimum value
160      @param max the maximum value
161      @param sum the sum of the recorded values
162      @param mean the arithmetic mean of values
163      @return an immutable object which contains statistical values
164      */
165     public static LongSummary of(
166         final long count,
167         final long min,
168         final long max,
169         final long sum,
170         final double mean
171     ) {
172         return new LongSummary(
173             count,
174             min,
175             max,
176             sum,
177             mean
178         );
179     }
180 
181     /**
182      * Return a new value object of the statistical summary, currently
183      * represented by the {@code statistics} object.
184      *
185      @param statistics the creating (mutable) statistics class
186      @return the statistical moments
187      */
188     public static LongSummary of(final LongSummaryStatistics statistics) {
189         return new LongSummary(
190             statistics.getCount(),
191             statistics.getMin(),
192             statistics.getMax(),
193             statistics.getSum(),
194             statistics.getAverage()
195         );
196     }
197 
198     /**
199      * Return a {@code Collector} which applies an long-producing mapping
200      * function to each input element, and returns summary-statistics for the
201      * resulting values.
202      *
203      <pre>{@code
204      * final Stream<SomeObject> stream = ...
205      * final LongSummary summary = stream
206      *     .collect(toLongSummary(v -> v.longValue()));
207      * }</pre>
208      *
209      @param mapper a mapping function to apply to each element
210      @param <T> the type of the input elements
211      @return a {@code Collector} implementing the summary-statistics reduction
212      @throws java.lang.NullPointerException if the given {@code mapper} is
213      *         {@code null}
214      */
215     public static <T> Collector<T, ?, LongSummary>
216     toLongSummary(final ToLongFunction<? super T> mapper) {
217         requireNonNull(mapper);
218         return Collector.of(
219             LongSummaryStatistics::new,
220             (a, b-> a.accept(mapper.applyAsLong(b)),
221             (a, b-> {a.combine(b)return a;},
222             LongSummary::of
223         );
224     }
225 
226 
227     /* *************************************************************************
228      * Some static helper methods.
229      **************************************************************************/
230 
231     /**
232      * Return the minimum value of the given double array.
233      *
234      @since 4.0
235      *
236      @param values the array.
237      @return the minimum value or {@link Long#MAX_VALUE} if the given array is
238      *         empty.
239      @throws NullPointerException if the given array is {@code null}.
240      */
241     public static long min(final long[] values) {
242         long min = Long.MAX_VALUE;
243         if (values.length > 0) {
244             min = values[0];
245 
246             for (int i = 0; i < values.length; ++i) {
247                 if (values[i< min) {
248                     min = values[i];
249                 }
250             }
251         }
252 
253         return min;
254     }
255 
256     /**
257      * Return the maximum value of the given double array.
258      *
259      @since 4.0
260      *
261      @param values the array.
262      @return the maximum value or {@link Long#MIN_VALUE} if the given array is
263      *         empty.
264      @throws NullPointerException if the given array is {@code null}.
265      */
266     public static long max(final long[] values) {
267         long max = Long.MIN_VALUE;
268         if (values.length > 0) {
269             max = values[0];
270 
271             for (int i = 0; i < values.length; ++i) {
272                 if (values[i> max) {
273                     max = values[i];
274                 }
275             }
276         }
277 
278         return max;
279     }
280 
281     /**
282      * Return the sum of the given double array.
283      *
284      @since 4.0
285      *
286      @param values the values to sum up.
287      @return the sum of the given {@code values}.
288      @throws NullPointerException if the given array is {@code null}.
289      */
290     public static long sum(final long[] values) {
291         long sum = 0;
292         for (int i = values.length; --i >= 0;) {
293             sum += values[i];
294         }
295         return sum;
296     }
297 
298     /**
299      * Returns a double describing the arithmetic mean of the values, or
300      {@link Double#NaN} if the {@code values} array is empty.
301      *
302      @since 4.0
303      *
304      @param values the values to calculate the mean of
305      @return the arithmetic mean of the given {@code values} or
306      *         {@link Double#NaN} if the {@code values} array is empty
307      @throws NullPointerException if the given array is {@code null}.
308      */
309     public static double mean(final long[] values) {
310         return values.length > (double)sum(values)/values.length : NaN;
311     }
312 
313 }