com.annimon.stream.Collectors Maven / Gradle / Ivy
/** Eclipse Class Decompiler plugin, Copyright (c) 2017 Chen Chao. */
/*
* Copyright (C) 2017 HaiYang Li
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.annimon.stream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.annimon.stream.function.BiConsumer;
import com.annimon.stream.function.BinaryOperator;
import com.annimon.stream.function.Consumer;
import com.annimon.stream.function.Function;
import com.annimon.stream.function.Predicate;
import com.annimon.stream.function.Supplier;
import com.annimon.stream.function.ToDoubleFunction;
import com.annimon.stream.function.ToIntFunction;
import com.annimon.stream.function.ToLongFunction;
/**
* Common implementations of {@code Collector} interface.
*
* @see Collector
*/
public final class Collectors {
private static final Supplier LONG_2ELEMENTS_ARRAY_SUPPLIER = new Supplier() {
@Override
public long[] get() {
return new long[] { 0L, 0L };
}
};
private static final Supplier DOUBLE_2ELEMENTS_ARRAY_SUPPLIER = new Supplier() {
@Override
public double[] get() {
return new double[] { 0d, 0d };
}
};
private Collectors() {
}
/**
* Returns a {@code Collector} that fills new {@code Collection}, provided by {@code collectionSupplier},
* with input elements.
*
* @param the type of the input elements
* @param the type of the resulting collection
* @param collectionSupplier a supplier function that provides new collection
* @return a {@code Collector}
*/
public static > Collector toCollection(Supplier collectionSupplier) {
return new CollectorsImpl<>(
collectionSupplier,
new BiConsumer() {
@Override
public void accept(R t, T u) {
t.add(u);
}
});
}
/**
* Returns a {@code Collector} that fills new {@code List} with input elements.
*
* @param the type of the input elements
* @return a {@code Collector}
*/
public static Collector> toList() {
return new CollectorsImpl<>(
new Supplier>() {
@Override
public List get() {
return new ArrayList<>();
}
},
new BiConsumer, T>() {
@Override
public void accept(List t, T u) {
t.add(u);
}
});
}
/**
* Returns a {@code Collector} that fills new {@code Set} with input elements.
*
* @param the type of the input elements
* @return a {@code Collector}
*/
public static Collector> toSet() {
return new CollectorsImpl<>(
new Supplier>() {
@Override
public Set get() {
return new HashSet<>();
}
},
new BiConsumer, T>() {
@Override
public void accept(Set t, T u) {
t.add(u);
}
});
}
/**
* Returns a {@code Collector} that fills new {@code Map} with input elements.
*
* @param the type of the input elements and the result type of value mapping function
* @param the result type of key mapping function
* @param keyMapper a mapping function to produce keys
* @return a {@code Collector}
* @see #toMap(Function, Function, BinaryOperator, Supplier)
* @since 1.1.3
*/
public static Collector> toMap(final Function super T, ? extends K> keyMapper) {
return toMap(keyMapper, Fn. identity());
}
/**
* Returns a {@code Collector} that fills new {@code Map} with input elements.
*
* @param the type of the input elements
* @param the result type of key mapping function
* @param the result type of value mapping function
* @param keyMapper a mapping function to produce keys
* @param valueMapper a mapping function to produce values
* @return a {@code Collector}
* @see #toMap(Function, Function, BinaryOperator, Supplier)
*/
public static Collector> toMap(final Function super T, ? extends K> keyMapper,
final Function super T, ? extends V> valueMapper) {
return toMap(keyMapper, valueMapper, Fn. throwingMerger());
}
/**
*
* @param keyMapper
* @param valueMapper
* @param mergeFunction
* @return
* @see #toMap(Function, Function, BinaryOperator, Supplier)
*/
public static Collector> toMap(final Function super T, ? extends K> keyMapper,
final Function super T, ? extends V> valueMapper, BinaryOperator mergeFunction) {
return toMap(keyMapper, valueMapper, mergeFunction, Fn.Suppliers. ofMap());
}
/**
*
* @param keyMapper
* @param valueMapper
* @param mapFactory
* @return
* @see #toMap(Function, Function, BinaryOperator, Supplier)
*/
public static > Collector toMap(final Function super T, ? extends K> keyMapper,
final Function super T, ? extends V> valueMapper, final Supplier mapFactory) {
return toMap(keyMapper, valueMapper, Fn. throwingMerger(), mapFactory);
}
/**
* Returns a {@code Collector} that fills new {@code Map} with input elements.
*
* @param the type of the input elements
* @param the result type of key mapping function
* @param the result type of value mapping function
* @param the type of the resulting {@code Map}
* @param keyMapper a mapping function to produce keys
* @param valueMapper a mapping function to produce values
* @param mergeFunction
* @param mapFactory a supplier function that provides new {@code Map}
* @return a {@code Collector}
*/
public static > Collector toMap(final Function super T, ? extends K> keyMapper,
final Function super T, ? extends V> valueMapper, final BinaryOperator mergeFunction, final Supplier mapFactory) {
return new CollectorsImpl<>(mapFactory, new BiConsumer() {
@Override
public void accept(M map, T t) {
final K key = keyMapper.apply(t);
final V value = valueMapper.apply(t);
if (map.containsKey(key)) {
map.put(key, mergeFunction.apply(map.get(key), value));
} else {
map.put(key, value);
}
}
});
}
/**
* Returns a {@code Collector} that concatenates input elements into new string.
*
* @return a {@code Collector}
*/
public static Collector joining() {
return joining("");
}
/**
* Returns a {@code Collector} that concatenates input elements into new string.
*
* @param delimiter the delimiter between each element
* @return a {@code Collector}
*/
public static Collector joining(CharSequence delimiter) {
return joining(delimiter, "", "");
}
/**
* Returns a {@code Collector} that concatenates input elements into new string.
*
* @param delimiter the delimiter between each element
* @param prefix the prefix of result
* @param suffix the suffix of result
* @return a {@code Collector}
*/
public static Collector joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) {
return joining(delimiter, prefix, suffix, prefix.toString() + suffix.toString());
}
/**
* Returns a {@code Collector} that concatenates input elements into new string.
*
* @param delimiter the delimiter between each element
* @param prefix the prefix of result
* @param suffix the suffix of result
* @param emptyValue the string which replaces empty element if exists
* @return a {@code Collector}
*/
public static Collector joining(final CharSequence delimiter, final CharSequence prefix, final CharSequence suffix,
final String emptyValue) {
return new CollectorsImpl<>(
new Supplier() {
@Override
public StringBuilder get() {
return new StringBuilder();
}
},
new BiConsumer() {
@Override
public void accept(StringBuilder t, CharSequence u) {
if (t.length() > 0) {
t.append(delimiter);
} else {
t.append(prefix);
}
t.append(u);
}
},
new Function() {
@Override
public String apply(StringBuilder value) {
if (value.length() == 0) {
return emptyValue;
} else {
value.append(suffix);
return value.toString();
}
}
});
}
/**
* Returns a {@code Collector} that calculates average of integer-valued input elements.
*
* @param the type of the input elements
* @param mapper the mapping function which extracts value from element to calculate result
* @return a {@code Collector}
* @since 1.1.3
*/
public static Collector averagingInt(final ToIntFunction super T> mapper) {
return averagingHelper(new BiConsumer() {
@Override
public void accept(long[] t, T u) {
t[0]++; // count
t[1] += mapper.applyAsInt(u); // sum
}
});
}
/**
* Returns a {@code Collector} that calculates average of long-valued input elements.
*
* @param the type of the input elements
* @param mapper the mapping function which extracts value from element to calculate result
* @return a {@code Collector}
* @since 1.1.3
*/
public static Collector averagingLong(final ToLongFunction super T> mapper) {
return averagingHelper(new BiConsumer() {
@Override
public void accept(long[] t, T u) {
t[0]++; // count
t[1] += mapper.applyAsLong(u); // sum
}
});
}
private static Collector averagingHelper(final BiConsumer accumulator) {
return new CollectorsImpl<>(
LONG_2ELEMENTS_ARRAY_SUPPLIER,
accumulator,
new Function() {
@Override
public Double apply(long[] t) {
if (t[0] == 0)
return 0d;
return t[1] / (double) t[0];
}
});
}
/**
* Returns a {@code Collector} that calculates average of double-valued input elements.
*
* @param the type of the input elements
* @param mapper the mapping function which extracts value from element to calculate result
* @return a {@code Collector}
* @since 1.1.3
*/
public static Collector averagingDouble(final ToDoubleFunction super T> mapper) {
return new CollectorsImpl<>(
DOUBLE_2ELEMENTS_ARRAY_SUPPLIER,
new BiConsumer() {
@Override
public void accept(double[] t, T u) {
t[0]++; // count
t[1] += mapper.applyAsDouble(u); // sum
}
},
new Function() {
@Override
public Double apply(double[] t) {
if (t[0] == 0)
return 0d;
return t[1] / t[0];
}
});
}
/**
* Returns a {@code Collector} that summing integer-valued input elements.
*
* @param the type of the input elements
* @param mapper the mapping function which extracts value from element to calculate result
* @return a {@code Collector}
* @since 1.1.3
*/
public static Collector summingInt(final ToIntFunction super T> mapper) {
return new CollectorsImpl<>(
new Supplier() {
@Override
public int[] get() {
return new int[] { 0 };
}
},
new BiConsumer() {
@Override
public void accept(int[] t, T u) {
t[0] += mapper.applyAsInt(u);
}
},
new Function() {
@Override
public Integer apply(int[] value) {
return value[0];
}
});
}
/**
* Returns a {@code Collector} that summing long-valued input elements.
*
* @param the type of the input elements
* @param mapper the mapping function which extracts value from element to calculate result
* @return a {@code Collector}
* @since 1.1.3
*/
public static Collector summingLong(final ToLongFunction super T> mapper) {
return new CollectorsImpl<>(
LONG_2ELEMENTS_ARRAY_SUPPLIER,
new BiConsumer() {
@Override
public void accept(long[] t, T u) {
t[0] += mapper.applyAsLong(u);
}
},
new Function() {
@Override
public Long apply(long[] value) {
return value[0];
}
});
}
/**
* Returns a {@code Collector} that summing double-valued input elements.
*
* @param the type of the input elements
* @param mapper the mapping function which extracts value from element to calculate result
* @return a {@code Collector}
* @since 1.1.3
*/
public static Collector summingDouble(final ToDoubleFunction super T> mapper) {
return new CollectorsImpl<>(
DOUBLE_2ELEMENTS_ARRAY_SUPPLIER,
new BiConsumer() {
@Override
public void accept(double[] t, T u) {
t[0] += mapper.applyAsDouble(u);
}
},
new Function() {
@Override
public Double apply(double[] value) {
return value[0];
}
});
}
/**
* Returns a {@code Collector} that counts the number of input elements.
*
* @param the type of the input elements
* @return a {@code Collector}
*/
public static Collector counting() {
return summingInt(new ToIntFunction() {
@Override
public int applyAsInt(T t) {
return 1;
}
});
}
/**
* Returns a {@code Collector} that reduces input elements.
*
* @param the type of the input elements
* @param identity the initial value
* @param op the operator to reduce elements
* @return a {@code Collector}
* @see #reducing(java.lang.Object, com.annimon.stream.function.Function, com.annimon.stream.function.BinaryOperator)
*/
public static Collector reducing(final T identity, final BinaryOperator op) {
return new CollectorsImpl<>(
new Supplier>() {
@Override
public Tuple1 get() {
return new Tuple1<>(identity);
}
},
new BiConsumer, T>() {
@Override
public void accept(Tuple1 tuple, T value) {
tuple.a = op.apply(tuple.a, value);
}
},
new Function, T>() {
@Override
public T apply(Tuple1 tuple) {
return tuple.a;
}
});
}
/**
* Returns a {@code Collector} that reduces input elements.
*
* @param the type of the input elements
* @param the type of the output elements
* @param identity the initial value
* @param mapper the mapping function
* @param op the operator to reduce elements
* @return a {@code Collector}
* @see #reducing(java.lang.Object, com.annimon.stream.function.BinaryOperator)
*/
public static Collector reducing(final R identity, final Function super T, ? extends R> mapper, final BinaryOperator op) {
return new CollectorsImpl<>(
new Supplier>() {
@Override
public Tuple1 get() {
return new Tuple1<>(identity);
}
},
new BiConsumer, T>() {
@Override
public void accept(Tuple1 tuple, T value) {
tuple.a = op.apply(tuple.a, mapper.apply(value));
}
},
new Function, R>() {
@Override
public R apply(Tuple1 tuple) {
return tuple.a;
}
});
}
/**
* Returns a {@code Collector} that filters input elements.
*
* @param the type of the input elements
* @param the accumulation type
* @param the type of the output elements
* @param predicate a predicate used to filter elements
* @param downstream the collector of filtered elements
* @return a {@code Collector}
* @since 1.1.3
*/
public static Collector filtering(final Predicate super T> predicate, final Collector super T, A, R> downstream) {
final BiConsumer accumulator = downstream.accumulator();
return new CollectorsImpl<>(
downstream.supplier(),
new BiConsumer() {
@Override
public void accept(A a, T t) {
if (predicate.test(t))
accumulator.accept(a, t);
}
},
downstream.finisher());
}
/**
* Returns a {@code Collector} that performs mapping before accumulation.
*
* @param the type of the input elements
* @param the result type of mapping function
* @param the accumulation type
* @param the result type of collector
* @param mapper a function that performs mapping to input elements
* @param downstream the collector of mapped elements
* @return a {@code Collector}
*/
public static Collector mapping(final Function super T, ? extends U> mapper, final Collector super U, A, R> downstream) {
final BiConsumer accumulator = downstream.accumulator();
return new CollectorsImpl<>(
downstream.supplier(),
new BiConsumer() {
@Override
public void accept(A a, T t) {
accumulator.accept(a, mapper.apply(t));
}
},
downstream.finisher());
}
/**
* Returns a {@code Collector} that performs flat-mapping before accumulation.
*
* @param the type of the input elements
* @param the result type of flat-mapping function
* @param the accumulation type
* @param the result type of collector
* @param mapper a function that performs flat-mapping to input elements
* @param downstream the collector of flat-mapped elements
* @return a {@code Collector}
* @since 1.1.3
*/
public static Collector flatMapping(final Function super T, ? extends Stream extends U>> mapper,
final Collector super U, A, R> downstream) {
final BiConsumer accumulator = downstream.accumulator();
return new CollectorsImpl<>(
downstream.supplier(),
new BiConsumer() {
@Override
public void accept(final A a, T t) {
final Stream extends U> stream = mapper.apply(t);
if (stream == null)
return;
stream.forEach(new Consumer() {
@Override
public void accept(U u) {
accumulator.accept(a, u);
}
});
}
},
downstream.finisher());
}
/**
* Returns a {@code Collector} that performs additional transformation.
*
* @param the type of the input elements
* @param the accumulation type
* @param the input type of the transformation function
* @param the output type of the transformation function
* @param c the input {@code Collector}
* @param finisher the final transformation function
* @return a {@code Collector}
*/
public static Collector collectingAndThen(final Collector c, final Function finisher) {
@SuppressWarnings({ "rawtypes", "unchecked" })
final Function downstreamFinisher = c.finisher() == null ? (Function) castIdentity() : c.finisher();
final Function newFinisher = new Function() {
@Override
public OR apply(A t) {
return finisher.apply(downstreamFinisher.apply(t));
}
};
return new CollectorsImpl<>(c.supplier(), c.accumulator(), newFinisher);
}
/**
* Returns a {@code Collector} that performs grouping operation by given classifier.
*
* @param the type of the input elements
* @param the type of the keys
* @param classifier the classifier function
* @return a {@code Collector}
* @see #groupingBy(com.annimon.stream.function.Function, com.annimon.stream.Collector)
* @see #groupingBy(com.annimon.stream.function.Function, com.annimon.stream.Collector, com.annimon.stream.function.Supplier)
*/
public static Collector>> groupingBy(Function super T, ? extends K> classifier) {
return groupingBy(classifier, Collectors. toList());
}
/**
* Returns a {@code Collector} that performs grouping operation by given classifier.
*
* @param the type of the input elements
* @param the type of the keys
* @param the accumulation type
* @param the result type of downstream reduction
* @param classifier the classifier function
* @param downstream the collector of mapped elements
* @return a {@code Collector}
* @see #groupingBy(com.annimon.stream.function.Function)
* @see #groupingBy(com.annimon.stream.function.Function, com.annimon.stream.Collector, com.annimon.stream.function.Supplier)
*/
public static Collector> groupingBy(Function super T, ? extends K> classifier, Collector super T, A, D> downstream) {
return Collectors.> groupingBy(classifier, downstream, Fn.Suppliers. ofMap());
}
/**
* Returns a {@code Collector} that performs grouping operation by given classifier.
*
* @param the type of the input elements
* @param the type of the keys
* @param the accumulation type
* @param the result type of downstream reduction
* @param the type of the resulting {@code Map}
* @param classifier the classifier function
* @param downstream the collector of mapped elements
* @param mapFactory a supplier function that provides new {@code Map}
* @return a {@code Collector}
* @see #groupingBy(com.annimon.stream.function.Function)
* @see #groupingBy(com.annimon.stream.function.Function, com.annimon.stream.Collector)
*/
public static > Collector groupingBy(final Function super T, ? extends K> classifier,
final Collector super T, A, D> downstream, final Supplier mapFactory) {
@SuppressWarnings("unchecked")
final Function downstreamFinisher = (Function) downstream.finisher();
Function
© 2015 - 2025 Weber Informatics LLC | Privacy Policy