All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kiwiproject.collect.KiwiCollectors Maven / Gradle / Ivy

Go to download

Kiwi is a utility library. We really like Google's Guava, and also use Apache Commons. But if they don't have something we need, and we think it is useful, this is where we put it.

There is a newer version: 4.5.2
Show newest version
package org.kiwiproject.collect;

import static org.kiwiproject.base.KiwiStrings.f;

import com.google.common.collect.ImmutableList;
import lombok.experimental.UtilityClass;

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * Utility for custom {@link java.util.stream.Collector} implementations
 */
@UtilityClass
public class KiwiCollectors {

    /**
     * Return a {@link Collector} that collects into a Guava {@link ImmutableList.Builder}. You only then need to
     * call {@link ImmutableList.Builder#build()}.
     *
     * @param  the type in the list
     * @return ImmutableList of {@code T}
     */
    public static  Collector, ImmutableList.Builder> toImmutableListBuilder() {
        return Collector.of(
                ImmutableList::builder,
                ImmutableList.Builder::add,
                (builder1, builder2) -> {
                    var listFromBuilder2 = builder2.build();
                    return builder1.addAll(listFromBuilder2);
                }
        );
    }

    /**
     * Returns a {@link Collector} that collects into an {@link EnumSet}.
     *
     * @param type the type in the {@link EnumSet}
     * @param   the enum type subclass
     * @return the {@link Collector}
     */
    public static > Collector, EnumSet> toEnumSet(Class type) {
        return Collector.of(
                () -> EnumSet.noneOf(type),
                Set::add,
                (enumSet1, enumSet2) -> {
                    enumSet1.addAll(enumSet2);
                    return enumSet1;
                }
        );
    }

    /**
     * Returns a {@link Collector} that collects into an {@link java.util.EnumMap}.
     * 

* If the mapped keys contain duplicates (according to {@link Object#equals(Object)}, an * {@code IllegalStateException} is thrown when the collection operation is performed. * * @param enumClass the key type for the returned map * @param keyMapper a mapping function to produce keys * @param valueMapper a mapping function to produce values * @param the type of the input elements * @param the output type of the key mapping function * @param the outptu type of the value mapping function * @return a {@link Collector} which collects elements into an {@link java.util.EnumMap} whose keys * are the result of applying key and value mapping functions. */ public static , U> Collector> toEnumMap( Class enumClass, Function keyMapper, Function valueMapper) { return Collectors.toMap( keyMapper, valueMapper, (u1, u2) -> { throw duplicateKeyException(u1, u2); }, () -> new EnumMap<>(enumClass) ); } /** * Returns a {@link Collector} that collects intoa {@link LinkedHashMap}. * * @param keyMapper a mapping function to produce keys * @param valueMapper a mapping function to produce values * @param the type of the input elements * @param the output type of the key mapping function * @param the output type of the value mapping function * @return a {@link Collector} which collects elements into a {@link java.util.LinkedHashMap} whose keys * are the result of applying key and value mapping functions. */ public static Collector> toLinkedMap( Function keyMapper, Function valueMapper) { return Collectors.toMap( keyMapper, valueMapper, (u1, u2) -> { throw duplicateKeyException(u1, u2); }, LinkedHashMap::new ); } /** * Used when a duplicate key occurs during a collection, returns a new {@link IllegalStateException}. * * @param u1 the first value supplied to the merge function * @param u2 the second value supplied to the merge function * @return a new {@link IllegalStateException} object * @implNote There is not an easy way to obtain the actual duplicate key here, since the merge function is a * {@link java.util.function.BinaryOperator} that accepts the two values needing to be merged. So unfortunately * the best we can easily do is report the values attempting to be merged, and let the person doing the * investigation hopefully backtrack to the duplicate key. */ private static IllegalStateException duplicateKeyException(Object u1, Object u2) { return new IllegalStateException(f("Duplicate key. Attempted to merge values {} and {}", u1, u2)); } }