001/* 002 * Java Genetic Algorithm Library (jenetics-7.2.0). 003 * Copyright (c) 2007-2023 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 */ 020package io.jenetics.stat; 021 022import static java.util.Objects.requireNonNull; 023 024import java.io.Serial; 025import java.io.Serializable; 026import java.util.function.ToIntFunction; 027import java.util.stream.Collector; 028 029/** 030 * <i>Value</i> objects which contains statistical moments. 031 * 032 * @see io.jenetics.stat.IntMomentStatistics 033 * 034 * @param count the count of values recorded 035 * @param min the minimum value recorded, or {@link Integer#MAX_VALUE} if no 036 * values have been recorded 037 * @param max the maximum value recorded, or {@link Integer#MIN_VALUE} if no 038 * values have been recorded 039 * @param sum the sum of values recorded, or zero if no values have been recorded 040 * @param mean the arithmetic mean of values recorded, or zero if no values have 041 * been recorded 042 * @param variance the variance of values recorded, or {@link Double#NaN} if no 043 * values have been recorded 044 * @param skewness the <a href="https://en.wikipedia.org/wiki/Skewness">Skewness</a> 045 * of values recorded, or {@link Double#NaN} if less than two values have 046 * been recorded 047 * @param kurtosis the <a href="https://en.wikipedia.org/wiki/Kurtosis">Kurtosis</a> 048 * of values recorded, or {@link Double#NaN} if less than four values 049 * have been recorded 050 * 051 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 052 * @since 3.0 053 * @version 7.0 054 */ 055public record IntMoments( 056 long count, 057 int min, 058 int max, 059 long sum, 060 double mean, 061 double variance, 062 double skewness, 063 double kurtosis 064) 065 implements Serializable 066{ 067 068 @Serial 069 private static final long serialVersionUID = 2L; 070 071 @Override 072 public String toString() { 073 return String.format( 074 "IntMoments[N=%d, ∧=%s, ∨=%s, Σ=%s, μ=%s, s²=%s, S=%s, K=%s]", 075 count(), min(), max(), sum(), 076 mean(), variance(), skewness(), kurtosis() 077 ); 078 } 079 080 /** 081 * Return a new value object of the statistical moments, currently 082 * represented by the {@code statistics} object. 083 * 084 * @param statistics the creating (mutable) statistics class 085 * @return the statistical moments 086 */ 087 public static IntMoments of(final IntMomentStatistics statistics) { 088 return new IntMoments( 089 statistics.count(), 090 statistics.min(), 091 statistics.max(), 092 statistics.sum(), 093 statistics.mean(), 094 statistics.variance(), 095 statistics.skewness(), 096 statistics.kurtosis() 097 ); 098 } 099 100 /** 101 * Return a {@code Collector} which returns moments-statistics for the 102 * resulting values. 103 * 104 * <pre>{@code 105 * final Stream<Integer> stream = ... 106 * final IntMoments moments = stream.collect(toIntMoments())); 107 * }</pre> 108 * 109 * @since 4.1 110 * 111 * @param <N> the type of the input elements 112 * @return a {@code Collector} implementing the moments-statistics reduction 113 */ 114 public static <N extends Number> Collector<N, ?, IntMoments> 115 toIntMoments() { 116 return toIntMoments(Number::intValue); 117 } 118 119 /** 120 * Return a {@code Collector} which applies an int-producing mapping 121 * function to each input element, and returns moments-statistics for the 122 * resulting values. 123 * 124 * <pre>{@code 125 * final Stream<SomeObject> stream = ... 126 * final IntMoments moments = stream 127 * .collect(toIntMoments(v -> v.intValue())); 128 * }</pre> 129 * 130 * @param mapper a mapping function to apply to each element 131 * @param <T> the type of the input elements 132 * @return a {@code Collector} implementing the moments-statistics reduction 133 * @throws java.lang.NullPointerException if the given {@code mapper} is 134 * {@code null} 135 */ 136 public static <T> Collector<T, ?, IntMoments> 137 toIntMoments(final ToIntFunction<? super T> mapper) { 138 requireNonNull(mapper); 139 return Collector.of( 140 IntMomentStatistics::new, 141 (a, b) -> a.accept(mapper.applyAsInt(b)), 142 IntMomentStatistics::combine, 143 IntMoments::of 144 ); 145 } 146 147}