MappedAccumulator.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-1.5.0).
003  * Copyright (c) 2007-2013 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.util;
021 
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 import static org.jenetics.util.object.eq;
025 import static org.jenetics.util.object.hashCodeOf;
026 
027 /**
028  * Abstract implementation of the {@link Accumulator} interface which defines a
029  * {@code samples} property which is incremented by the {@link #accumulate(Object)}
030  * method.
031  *
032  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
033  @since 1.0
034  @version 1.0 &mdash; <em>$Date: 2013-09-01 $</em>
035  */
036 public abstract class MappedAccumulator<T>
037     implements
038         Accumulator<T>,
039         Cloneable
040 {
041 
042     /**
043      * The number of accumulated samples.
044      */
045     protected long _samples = 0;
046 
047     protected MappedAccumulator() {
048     }
049 
050     /**
051      * Return the number of samples accumulated so far.
052      *
053      @return the number of samples accumulated so far.
054      */
055     public long getSamples() {
056         return _samples;
057     }
058 
059     @Override
060     public void accumulate(final T value) {
061         ++_samples;
062     }
063 
064     /**
065      * Return a view of this adapter with a different type {@code B}.
066      *
067      * Usage example:
068      * [code]
069      * // Convert a string on the fly into a double value.
070      * final Converter<String, Double> converter = new Converter<String, Double>() {
071      *         public Double convert(final String value) {
072      *             return Double.valueOf(value);
073      *         }
074      *     };
075      *
076      * // The values to accumulate
077      * final List<String> values = Arrays.asList("0", "1", "2", "3", "4", "5");
078      *
079      * final Accumulators.Min<Double> accumulator = new Accumulators.Min<Double>();
080      *
081      * // No pain to accumulate collections of a different type.
082      * Accumulators.accumulate(values, accumulator.map(converter));
083      * [/code]
084      *
085      @param <B> the type of the returned adapter (view).
086      @param mapper the mapper needed to map between the type of this
087      *        adapter and the adapter view type.
088      @return the adapter view with the different type.
089      @throws NullPointerException if the given {@code converter} is {@code null}.
090      */
091     public <B> MappedAccumulator<B> map(final Function<? super B, ? extends T> mapper) {
092         requireNonNull(mapper, "Mapper");
093         return new MappedAccumulator<B>() {
094             @Override
095             public void accumulate(final B value) {
096                 MappedAccumulator.this.accumulate(mapper.apply(value));
097             }
098         };
099     }
100 
101     @Override
102     public int hashCode() {
103         return hashCodeOf(getClass()).and(_samples).value();
104     }
105 
106     @Override
107     public boolean equals(final Object obj) {
108         if (obj == this) {
109             return true;
110         }
111         if (obj == null || getClass() != obj.getClass()) {
112             return false;
113         }
114 
115         final MappedAccumulator<?> accumulator = (MappedAccumulator<?>)obj;
116         return eq(_samples, accumulator._samples);
117     }
118 
119     @Override
120     public String toString() {
121         return format(
122                 "%s[samples=%d]", getClass().getName(), _samples
123             );
124     }
125 
126     @SuppressWarnings("unchecked")
127     @Override
128     protected MappedAccumulator<T> clone() {
129         try {
130             return (MappedAccumulator<T>)super.clone();
131         catch (CloneNotSupportedException e) {
132             throw new AssertionError(e);
133         }
134     }
135 
136 }