MinMax.java
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<= ? 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>= ? 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 }