001 /*
002 * Java Genetic Algorithm Library (jenetics-3.5.0).
003 * Copyright (c) 2007-2016 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@gmx.at)
019 */
020 package org.jenetics.stat;
021
022 import static java.util.Objects.requireNonNull;
023
024 import java.util.Comparator;
025 import java.util.function.Consumer;
026 import java.util.stream.Collector;
027
028 /**
029 * This <i>consumer</i> class is used for calculating the min and max value
030 * according to the given {@code Comparator}.
031 * <p>
032 * This class is designed to work with (though does not require) streams. For
033 * example, you can compute minimum and maximum values with:
034 * <pre>{@code
035 * final Stream<Integer> stream = ...
036 * final MinMax<Integer> minMax = stream.collect(
037 * MinMax::of,
038 * MinMax::accept,
039 * MinMax::combine
040 * );
041 * }</pre>
042 *
043 * <p>
044 * <b>Implementation note:</b>
045 * <i>This implementation is not thread safe. However, it is safe to use on a
046 * parallel stream, because the parallel implementation of
047 * {@link java.util.stream.Stream#collect Stream.collect()}provides the
048 * necessary partitioning, isolation, and merging of results for safe and
049 * efficient parallel execution.</i>
050 *
051 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
052 * @since 3.0
053 * @version 3.0
054 */
055 public final class MinMax<C> implements Consumer<C> {
056
057 private final Comparator<? super C> _comparator;
058
059 private C _min;
060 private C _max;
061 private long _count = 0L;
062
063 private MinMax(final Comparator<? super C> comparator) {
064 _comparator = requireNonNull(comparator);
065 }
066
067 /**
068 * Accept the element for min-max calculation.
069 *
070 * @param object the element to use for min-max calculation
071 */
072 @Override
073 public void accept(final C object) {
074 _min = min(_comparator, _min, object);
075 _max = max(_comparator, _max, object);
076 ++_count;
077 }
078
079 /**
080 * Combine two {@code MinMax} objects.
081 *
082 * @param other the other {@code MinMax} object to combine
083 * @return {@code this}
084 * @throws java.lang.NullPointerException if the {@code other} object is
085 * {@code null}.
086 */
087 public MinMax<C> combine(final MinMax<C> other) {
088 _min = min(_comparator, _min, other._min);
089 _max = max(_comparator, _max, other._max);
090 _count += other._count;
091
092 return this;
093 }
094
095 /**
096 * Return the current minimal object or {@code null} if no element has been
097 * accepted yet.
098 *
099 * @return the current minimal object
100 */
101 public C getMin() {
102 return _min;
103 }
104
105 /**
106 * Return the current maximal object or {@code null} if no element has been
107 * accepted yet.
108 *
109 * @return the current maximal object
110 */
111 public C getMax() {
112 return _max;
113 }
114
115 /**
116 * Returns the count of values recorded.
117 *
118 * @return the count of recorded values
119 */
120 public long getCount() {
121 return _count;
122 }
123
124 /* *************************************************************************
125 * Some static helper methods.
126 * ************************************************************************/
127
128 /**
129 * Return the minimum of two values, according the given comparator.
130 * {@code null} values are allowed.
131 *
132 * @param comp the comparator used for determining the min value
133 * @param a the first value to compare
134 * @param b the second value to compare
135 * @param <T> the type of the compared objects
136 * @return the minimum value, or {@code null} if both values are {@code null}.
137 * If only one value is {@code null}, the non {@code null} values is
138 * returned.
139 */
140 public static <T> T
141 min(final Comparator<? super T> comp, final T a, final T b) {
142 return a != null ? b != null ? comp.compare(a, b) <= 0 ? a : b : a : b;
143 }
144
145 /**
146 * Return the maximum of two values, according the given comparator.
147 * {@code null} values are allowed.
148 *
149 * @param comp the comparator used for determining the max value
150 * @param a the first value to compare
151 * @param b the second value to compare
152 * @param <T> the type of the compared objects
153 * @return the maximum value, or {@code null} if both values are {@code null}.
154 * If only one value is {@code null}, the non {@code null} values is
155 * returned.
156 */
157 public static <T> T
158 max(final Comparator<? super T> comp, final T a, final T b) {
159 return a != null ? b != null ? comp.compare(a, b) >= 0 ? a : b : a : b;
160 }
161
162
163 /* *************************************************************************
164 * Some static factory methods.
165 * ************************************************************************/
166
167 /**
168 * Return a {@code Collector} which calculates the minimum and maximum value.
169 * The given {@code comparator} is used for comparing two objects.
170 *
171 * <pre>{@code
172 * final Comparator<SomeObject> comparator = ...
173 * final Stream<SomeObject> stream = ...
174 * final MinMax<SomeObject> moments = stream
175 * .collect(doubleMoments.toMinMax(comparator));
176 * }</pre>
177 *
178 * @param comparator the {@code Comparator} to use
179 * @param <T> the type of the input elements
180 * @return a {@code Collector} implementing the min-max reduction
181 * @throws java.lang.NullPointerException if the given {@code mapper} is
182 * {@code null}
183 */
184 public static <T>
185 Collector<T, ?, MinMax<T>> toMinMax(final Comparator<? super T> comparator) {
186 return Collector.of(
187 () -> MinMax.of(comparator),
188 MinMax::accept,
189 MinMax::combine
190 );
191 }
192
193 /**
194 * Return a {@code Collector} which calculates the minimum and maximum value.
195 * The <i>reducing</i> objects must be comparable.
196 *
197 * <pre>{@code
198 * final Stream<SomeObject> stream = ...
199 * final MinMax<SomeObject> moments = stream
200 * .collect(doubleMoments.toMinMax(comparator));
201 * }</pre>
202 *
203 * @param <C> the type of the input elements
204 * @return a {@code Collector} implementing the min-max reduction
205 * @throws java.lang.NullPointerException if the given {@code mapper} is
206 * {@code null}
207 */
208 public static <C extends Comparable<? super C>>
209 Collector<C, ?, MinMax<C>> toMinMax() {
210 return toMinMax((a, b) -> a.compareTo(b));
211 }
212
213 /**
214 * Create a new {@code MinMax} <i>consumer</i> with the given
215 * {@link java.util.Comparator}.
216 *
217 * @param comparator the comparator used for comparing two elements
218 * @param <T> the element type
219 * @return a new {@code MinMax} <i>consumer</i>
220 * @throws java.lang.NullPointerException if the {@code comparator} is
221 * {@code null}.
222 */
223 public static <T> MinMax<T> of(final Comparator<? super T> comparator) {
224 return new MinMax<>(comparator);
225 }
226
227 /**
228 * Create a new {@code MinMax} <i>consumer</i>.
229 *
230 * @param <C> the element type
231 * @return a new {@code MinMax} <i>consumer</i>
232 */
233 public static <C extends Comparable<? super C>> MinMax<C> of() {
234 return of((a, b) -> a.compareTo(b));
235 }
236
237 }
|