
no.digipost.DiggCollectors Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of digg Show documentation
Show all versions of digg Show documentation
Some stellar general purpose utils.
The newest version!
/**
* Copyright (C) Posten Norge AS
*
* 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 no.digipost;
import no.digipost.collection.AdaptableCollector;
import no.digipost.collection.EnforceAtMostOneElementCollector;
import no.digipost.concurrent.OneTimeAssignment;
import no.digipost.tuple.Tuple;
import no.digipost.tuple.ViewableAsTuple;
import no.digipost.util.ViewableAsOptional;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.Collections.unmodifiableList;
/**
* Various {@link java.util.stream.Collector} implementations.
*/
@SuppressWarnings("deprecation")
public final class DiggCollectors {
/**
* A multimap maps from keys to lists, and this collector will arrange {@link ViewableAsTuple tuples}
* by putting each distinct {@link Tuple#first() first tuple-element} as keys of the resulting map, mapping
* them to a {@link List}, and adding each {@link Tuple#second() second tuple-element} to the list.
*
* @param The type of the first tuple element, which will become the key type of the resulting {@code Map}.
* @param The type of the second tuple element, which will become the {@code List} value type of the
* resulting {@code Map}.
*
* @return the multimap collector.
*/
public static AdaptableCollector>, ?, Map>> toMultimap() {
Function>, Tuple>> asTuple = ViewableAsTuple::asTuple;
return toMultimap(asTuple.andThen(Tuple::first), asTuple.andThen(Tuple::second));
}
public static AdaptableCollector>> toMultimap(Function super T, Optional> extractor) {
return toMultimap(Function.identity(), extractor);
}
public static AdaptableCollector>> toMultimap(Function super T, K> keyExtractor, Function super T, Optional> extractor) {
return adapt(Collectors.toMap(keyExtractor, extractor.andThen(DiggOptionals::toList), DiggCollectors::concat));
}
/**
* This is a collector for accessing the expected singular only element of a {@link Stream}, as
* it will throw an exception if more than one element is processed. This should be used in
* preference of the {@link Stream#findFirst()} or {@link Stream#findAny()} when it is imperative
* that the stream indeed yields a maximum of one single element, and any more elements is
* considered a programming error.
*
* @return the collector
*/
public static AdaptableCollector, Optional> allowAtMostOne() {
return allowAtMostOneOrElseThrow(ViewableAsOptional.TooManyElements::new);
}
/**
* This is a collector for accessing the expected singular only element of a {@link Stream}, as
* it will throw the exception yielded from the given function if more than one element is processed.
*
* @param the function will be given the first element yielded from the stream as its first argument
* and the unexpected excess one as the second, which may be used to construct an
* exception to be thrown.
* @return the collector
* @see #allowAtMostOne()
*/
public static AdaptableCollector, Optional> allowAtMostOneOrElseThrow(BiFunction super T, ? super T, ? extends RuntimeException> exceptionOnExcessiveElements) {
return adapt(new EnforceAtMostOneElementCollector<>(exceptionOnExcessiveElements));
}
/**
* Turn any {@link Collector} into an {@link AdaptableCollector}.
*
* @param collector the collector to convert
*
* @return the {@link AdaptableCollector}
*
* @see AdaptableCollector
* @deprecated Use {@link Collectors#collectingAndThen(Collector, Function)} instead.
*/
@Deprecated
public static AdaptableCollector adapt(Collector collector) {
if (collector instanceof AdaptableCollector) {
return (AdaptableCollector) collector;
} else {
return AdaptableCollector.of(collector.supplier(), collector.accumulator(), collector.combiner(), collector.finisher(), collector.characteristics());
}
}
private static List concat(Collection extends T> list1, Collection extends T> list2) {
List newList = new ArrayList<>(list1.size() + list2.size());
newList.addAll(list1);
newList.addAll(list2);
return unmodifiableList(newList);
}
private DiggCollectors() {}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy