Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.google.common.collect.CollectCollectors Maven / Gradle / Ivy
/*
* Copyright (C) 2016 The Guava Authors
*
* 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.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Collections.singletonMap;
import static java.util.stream.Collectors.collectingAndThen;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Preconditions;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.TreeMap;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.ToIntFunction;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.Nullable;
/** Collectors utilities for {@code common.collect} internals. */
@GwtCompatible
@ElementTypesAreNonnullByDefault
final class CollectCollectors {
private static final Collector> TO_IMMUTABLE_LIST =
Collector.of(
ImmutableList::builder,
ImmutableList.Builder::add,
ImmutableList.Builder::combine,
ImmutableList.Builder::build);
private static final Collector> TO_IMMUTABLE_SET =
Collector.of(
ImmutableSet::builder,
ImmutableSet.Builder::add,
ImmutableSet.Builder::combine,
ImmutableSet.Builder::build);
@GwtIncompatible
private static final Collector>, ?, ImmutableRangeSet>>
TO_IMMUTABLE_RANGE_SET =
Collector.of(
ImmutableRangeSet::builder,
ImmutableRangeSet.Builder::add,
ImmutableRangeSet.Builder::combine,
ImmutableRangeSet.Builder::build);
// Lists
@SuppressWarnings({"rawtypes", "unchecked"})
static Collector> toImmutableList() {
return (Collector) TO_IMMUTABLE_LIST;
}
// Sets
@SuppressWarnings({"rawtypes", "unchecked"})
static Collector> toImmutableSet() {
return (Collector) TO_IMMUTABLE_SET;
}
static Collector> toImmutableSortedSet(
Comparator super E> comparator) {
checkNotNull(comparator);
return Collector.of(
() -> new ImmutableSortedSet.Builder(comparator),
ImmutableSortedSet.Builder::add,
ImmutableSortedSet.Builder::combine,
ImmutableSortedSet.Builder::build);
}
@SuppressWarnings({"rawtypes", "unchecked"})
static > Collector> toImmutableEnumSet() {
return (Collector) EnumSetAccumulator.TO_IMMUTABLE_ENUM_SET;
}
private static >
Collector, ImmutableSet> toImmutableEnumSetGeneric() {
return Collector.of(
EnumSetAccumulator::new,
EnumSetAccumulator::add,
EnumSetAccumulator::combine,
EnumSetAccumulator::toImmutableSet,
Collector.Characteristics.UNORDERED);
}
private static final class EnumSetAccumulator> {
@SuppressWarnings({"rawtypes", "unchecked"})
static final Collector, ?, ImmutableSet extends Enum>>> TO_IMMUTABLE_ENUM_SET =
(Collector) toImmutableEnumSetGeneric();
@CheckForNull private EnumSet set;
void add(E e) {
if (set == null) {
set = EnumSet.of(e);
} else {
set.add(e);
}
}
EnumSetAccumulator combine(EnumSetAccumulator other) {
if (this.set == null) {
return other;
} else if (other.set == null) {
return this;
} else {
this.set.addAll(other.set);
return this;
}
}
ImmutableSet toImmutableSet() {
if (set == null) {
return ImmutableSet.of();
}
ImmutableSet ret = ImmutableEnumSet.asImmutable(set);
set = null; // subsequent manual manipulation of the accumulator mustn't affect ret
return ret;
}
}
@GwtIncompatible
@SuppressWarnings({"rawtypes", "unchecked"})
static >
Collector, ?, ImmutableRangeSet> toImmutableRangeSet() {
return (Collector) TO_IMMUTABLE_RANGE_SET;
}
// Multisets
static Collector> toImmutableMultiset(
Function super T, ? extends E> elementFunction, ToIntFunction super T> countFunction) {
checkNotNull(elementFunction);
checkNotNull(countFunction);
return Collector.of(
LinkedHashMultiset::create,
(multiset, t) ->
multiset.add(checkNotNull(elementFunction.apply(t)), countFunction.applyAsInt(t)),
(multiset1, multiset2) -> {
multiset1.addAll(multiset2);
return multiset1;
},
(Multiset multiset) -> ImmutableMultiset.copyFromEntries(multiset.entrySet()));
}
static >
Collector toMultiset(
Function super T, E> elementFunction,
ToIntFunction super T> countFunction,
Supplier multisetSupplier) {
checkNotNull(elementFunction);
checkNotNull(countFunction);
checkNotNull(multisetSupplier);
return Collector.of(
multisetSupplier,
(ms, t) -> ms.add(elementFunction.apply(t), countFunction.applyAsInt(t)),
(ms1, ms2) -> {
ms1.addAll(ms2);
return ms1;
});
}
// Maps
static Collector> toImmutableMap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends V> valueFunction) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
return Collector.of(
ImmutableMap.Builder::new,
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
ImmutableMap.Builder::combine,
ImmutableMap.Builder::buildOrThrow);
}
static Collector> toImmutableMap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends V> valueFunction,
BinaryOperator mergeFunction) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
checkNotNull(mergeFunction);
return collectingAndThen(
Collectors.toMap(keyFunction, valueFunction, mergeFunction, LinkedHashMap::new),
ImmutableMap::copyOf);
}
static
Collector> toImmutableSortedMap(
Comparator super K> comparator,
Function super T, ? extends K> keyFunction,
Function super T, ? extends V> valueFunction) {
checkNotNull(comparator);
checkNotNull(keyFunction);
checkNotNull(valueFunction);
/*
* We will always fail if there are duplicate keys, and the keys are always sorted by
* the Comparator, so the entries can come in an arbitrary order -- so we report UNORDERED.
*/
return Collector.of(
() -> new ImmutableSortedMap.Builder(comparator),
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
ImmutableSortedMap.Builder::combine,
ImmutableSortedMap.Builder::buildOrThrow,
Collector.Characteristics.UNORDERED);
}
static
Collector> toImmutableSortedMap(
Comparator super K> comparator,
Function super T, ? extends K> keyFunction,
Function super T, ? extends V> valueFunction,
BinaryOperator mergeFunction) {
checkNotNull(comparator);
checkNotNull(keyFunction);
checkNotNull(valueFunction);
checkNotNull(mergeFunction);
return collectingAndThen(
Collectors.toMap(
keyFunction, valueFunction, mergeFunction, () -> new TreeMap(comparator)),
ImmutableSortedMap::copyOfSorted);
}
static Collector> toImmutableBiMap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends V> valueFunction) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
return Collector.of(
ImmutableBiMap.Builder::new,
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
ImmutableBiMap.Builder::combine,
ImmutableBiMap.Builder::buildOrThrow,
new Collector.Characteristics[0]);
}
static , V>
Collector> toImmutableEnumMap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends V> valueFunction) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
return Collector.of(
() ->
new EnumMapAccumulator(
(v1, v2) -> {
throw new IllegalArgumentException("Multiple values for key: " + v1 + ", " + v2);
}),
(accum, t) -> {
/*
* We assign these to variables before calling checkNotNull to work around a bug in our
* nullness checker.
*/
K key = keyFunction.apply(t);
V newValue = valueFunction.apply(t);
accum.put(
checkNotNull(key, "Null key for input %s", t),
checkNotNull(newValue, "Null value for input %s", t));
},
EnumMapAccumulator::combine,
EnumMapAccumulator::toImmutableMap,
Collector.Characteristics.UNORDERED);
}
static , V>
Collector> toImmutableEnumMap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends V> valueFunction,
BinaryOperator mergeFunction) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
checkNotNull(mergeFunction);
// not UNORDERED because we don't know if mergeFunction is commutative
return Collector.of(
() -> new EnumMapAccumulator(mergeFunction),
(accum, t) -> {
/*
* We assign these to variables before calling checkNotNull to work around a bug in our
* nullness checker.
*/
K key = keyFunction.apply(t);
V newValue = valueFunction.apply(t);
accum.put(
checkNotNull(key, "Null key for input %s", t),
checkNotNull(newValue, "Null value for input %s", t));
},
EnumMapAccumulator::combine,
EnumMapAccumulator::toImmutableMap);
}
private static class EnumMapAccumulator, V> {
private final BinaryOperator mergeFunction;
@CheckForNull private EnumMap map = null;
EnumMapAccumulator(BinaryOperator mergeFunction) {
this.mergeFunction = mergeFunction;
}
void put(K key, V value) {
if (map == null) {
map = new EnumMap<>(singletonMap(key, value));
} else {
map.merge(key, value, mergeFunction);
}
}
EnumMapAccumulator combine(EnumMapAccumulator other) {
if (this.map == null) {
return other;
} else if (other.map == null) {
return this;
} else {
other.map.forEach(this::put);
return this;
}
}
ImmutableMap toImmutableMap() {
return (map == null) ? ImmutableMap.of() : ImmutableEnumMap.asImmutable(map);
}
}
@GwtIncompatible
static , V>
Collector> toImmutableRangeMap(
Function super T, Range> keyFunction,
Function super T, ? extends V> valueFunction) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
return Collector.of(
ImmutableRangeMap::builder,
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
ImmutableRangeMap.Builder::combine,
ImmutableRangeMap.Builder::build);
}
// Multimaps
static
Collector> toImmutableListMultimap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends V> valueFunction) {
checkNotNull(keyFunction, "keyFunction");
checkNotNull(valueFunction, "valueFunction");
return Collector.of(
ImmutableListMultimap::builder,
(builder, t) -> builder.put(keyFunction.apply(t), valueFunction.apply(t)),
ImmutableListMultimap.Builder::combine,
ImmutableListMultimap.Builder::build);
}
static
Collector> flatteningToImmutableListMultimap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends Stream extends V>> valuesFunction) {
checkNotNull(keyFunction);
checkNotNull(valuesFunction);
return collectingAndThen(
flatteningToMultimap(
input -> checkNotNull(keyFunction.apply(input)),
input -> valuesFunction.apply(input).peek(Preconditions::checkNotNull),
MultimapBuilder.linkedHashKeys().arrayListValues()::build),
ImmutableListMultimap::copyOf);
}
static
Collector> toImmutableSetMultimap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends V> valueFunction) {
checkNotNull(keyFunction, "keyFunction");
checkNotNull(valueFunction, "valueFunction");
return Collector.of(
ImmutableSetMultimap::builder,
(builder, t) -> builder.put(keyFunction.apply(t), valueFunction.apply(t)),
ImmutableSetMultimap.Builder::combine,
ImmutableSetMultimap.Builder::build);
}
static
Collector> flatteningToImmutableSetMultimap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends Stream extends V>> valuesFunction) {
checkNotNull(keyFunction);
checkNotNull(valuesFunction);
return collectingAndThen(
flatteningToMultimap(
input -> checkNotNull(keyFunction.apply(input)),
input -> valuesFunction.apply(input).peek(Preconditions::checkNotNull),
MultimapBuilder.linkedHashKeys().linkedHashSetValues()::build),
ImmutableSetMultimap::copyOf);
}
static <
T extends @Nullable Object,
K extends @Nullable Object,
V extends @Nullable Object,
M extends Multimap>
Collector toMultimap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends V> valueFunction,
Supplier multimapSupplier) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
checkNotNull(multimapSupplier);
return Collector.of(
multimapSupplier,
(multimap, input) -> multimap.put(keyFunction.apply(input), valueFunction.apply(input)),
(multimap1, multimap2) -> {
multimap1.putAll(multimap2);
return multimap1;
});
}
static <
T extends @Nullable Object,
K extends @Nullable Object,
V extends @Nullable Object,
M extends Multimap>
Collector flatteningToMultimap(
Function super T, ? extends K> keyFunction,
Function super T, ? extends Stream extends V>> valueFunction,
Supplier multimapSupplier) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
checkNotNull(multimapSupplier);
return Collector.of(
multimapSupplier,
(multimap, input) -> {
K key = keyFunction.apply(input);
Collection valuesForKey = multimap.get(key);
valueFunction.apply(input).forEachOrdered(valuesForKey::add);
},
(multimap1, multimap2) -> {
multimap1.putAll(multimap2);
return multimap1;
});
}
private CollectCollectors() {}
}