001/* 002 * Java Genetic Algorithm Library (jenetics-8.1.0). 003 * Copyright (c) 2007-2024 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 * {@snippet lang="java": 104 * final Stream<Integer> stream = null; // @replace substring='null' replacement="..." 105 * final IntMoments moments = stream.collect(toIntMoments()); 106 * } 107 * 108 * @since 4.1 109 * 110 * @param <N> the type of the input elements 111 * @return a {@code Collector} implementing the moments-statistics reduction 112 */ 113 public static <N extends Number> Collector<N, ?, IntMoments> 114 toIntMoments() { 115 return toIntMoments(Number::intValue); 116 } 117 118 /** 119 * Return a {@code Collector} which applies an int-producing mapping 120 * function to each input element, and returns moments-statistics for the 121 * resulting values. 122 * {@snippet lang="java": 123 * final Stream<SomeObject> stream = null; // @replace substring='null' replacement="..." 124 * final IntMoments moments = stream 125 * .collect(toIntMoments(v -> v.intValue())); 126 * } 127 * 128 * @param mapper a mapping function to apply to each element 129 * @param <T> the type of the input elements 130 * @return a {@code Collector} implementing the moments-statistics reduction 131 * @throws java.lang.NullPointerException if the given {@code mapper} is 132 * {@code null} 133 */ 134 public static <T> Collector<T, ?, IntMoments> 135 toIntMoments(final ToIntFunction<? super T> mapper) { 136 requireNonNull(mapper); 137 return Collector.of( 138 IntMomentStatistics::new, 139 (a, b) -> a.accept(mapper.applyAsInt(b)), 140 IntMomentStatistics::combine, 141 IntMoments::of 142 ); 143 } 144 145}