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

com.yahoo.bard.webservice.util.StreamUtils Maven / Gradle / Ivy

Go to download

Fili web service library provides core capabilities for RESTful aggregation navigation, query planning and metadata

There is a newer version: 1.1.13
Show newest version
// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms.
package com.yahoo.bard.webservice.util;

import static com.yahoo.bard.webservice.web.ErrorMessageFormat.TWO_VALUES_OF_THE_SAME_KEY;

import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Utils for dealing with streams.
 */
public class StreamUtils {
    /**
     * Returns a merge function, suitable for use in
     * {@link java.util.Map#merge(Object, Object, java.util.function.BiFunction) Map.merge()} or
     * {@link Collectors#toMap(Function, Function, BinaryOperator) toMap()}, which always
     * throws {@code IllegalStateException}.  This can be used to enforce the
     * assumption that the elements being collected are distinct.
     *
     * @param  the type of input arguments to the merge function
     *
     * @return a merge function which always throw {@code IllegalStateException}
     * @see Collectors#throwingMerger()
     */
    public static  BinaryOperator throwingMerger() {
        return (u, v) -> { throw new IllegalStateException(TWO_VALUES_OF_THE_SAME_KEY.format(u, v)); };
    }

    /**
     * Return a collector that creates a LinkedHashMap using the given key and value functions.
     * This collector assumes the elements being collected are distinct.
     *
     * @param   Type of the objects being collected
     * @param   Type of the keys
     * @param   Type of the values
     * @param keyMapper  Mapping function for the key
     * @param valueMapper  Mapping function for the value
     *
     * @return a collector that creates a LinkedHashMap using the given key and value functions.
     * @throws IllegalStateException if multiple values are associated with the same key
     * @see Collectors#toMap(Function, Function, BinaryOperator, java.util.function.Supplier)
     */
    public static  Collector> toLinkedMap(
            Function keyMapper,
            Function valueMapper
    ) {
        return Collectors.toMap(keyMapper, valueMapper, StreamUtils.throwingMerger(), LinkedHashMap::new);
    }

    /**
     * Return a collector that creates a {@link java.util.Map} using the given key and value functions.
     * This collector assumes the elements being collected are distinct.
     * 

* The concrete type of the {@link java.util.Map} being created is given by a {@link java.util.function.Supplier}. * * @param Type of the objects being collected * @param Type of the keys * @param Type of the values * @param The type of Map being collected into * @param keyMapper Mapping function for the key * @param valueMapper Mapping function for the value * @param mapSupplier A {@link java.util.function.Supplier} which provides a new, empty {@link java.util.Map} into * which the results will be inserted * * @return a collector that creates a {@link java.util.Map} using the given key and value functions * @throws IllegalStateException if multiple values are associated with the same key * @see Collectors#toMap(Function, Function, BinaryOperator, java.util.function.Supplier) */ public static > Collector toMap( Function keyMapper, Function valueMapper, Supplier mapSupplier ) { return Collectors.toMap(keyMapper, valueMapper, StreamUtils.throwingMerger(), mapSupplier); } /** * Return a collector that creates a LinkedHashMap dictionary using the given key function. * This collector assumes the elements being collected are distinct. * * @param Type of the objects being collected and the values of the dictionary / map * @param Type of the keys * @param keyMapper Mapping function for the key * * @return a collector that creates a LinkedHashMap dictionary using the given key function. * @throws IllegalStateException if multiple values are associated with the same key * @see Collectors#toMap(Function, Function, BinaryOperator, java.util.function.Supplier) */ public static Collector> toLinkedDictionary( Function keyMapper ) { return Collectors.toMap(keyMapper, Function.identity(), StreamUtils.throwingMerger(), LinkedHashMap::new); } /** * Return a collector that creates a dictionary using the given key function and the given map supplier. * This collector assumes the elements being collected are distinct. * * @param Type of the objects being collected and the values of the dictionary / map * @param Type of the keys * @param The type of Map being collected into * @param keyMapper Mapping function for the key * @param mapSupplier A {@link java.util.function.Supplier} which provides a new, empty {@link java.util.Map} into * which the results will be inserted * * @return a {@link java.util.stream.Collector} that creates a dictionary using the given * {@link java.util.function.Function key function} and the given {@link java.util.function.Supplier map supplier} * @throws IllegalStateException if multiple values are associated with the same key * @see Collectors#toMap(Function, Function, BinaryOperator, java.util.function.Supplier) */ public static > Collector toDictionary( Function keyMapper, Supplier mapSupplier ) { return Collectors.toMap(keyMapper, Function.identity(), StreamUtils.throwingMerger(), mapSupplier); } /** * Collect a stream into an unmodifiable set preserving first-in ordering. * * @param The type of the value stream * @param values The stream of values to be collected * * @return An unmodifiable copy of a linked hash set view of the stream */ public static Set toUnmodifiableSet(Stream values) { return Collections.unmodifiableSet((Set) values.collect(Collectors.toCollection(LinkedHashSet::new))); } /** * Negate the given predicate. * * @param Type of the predicate being negated * @param predicate Predicate to negate * * @return the negated predicate */ public static Predicate not(Predicate predicate) { return predicate.negate(); } /** * Return a function that can be used to do unchecked casts without generating a compiler warning. *

* Essentially the same as annotating the cast with {@code @SuppressWarnings("unchecked")}, which you can't do * inside a stream. * * @param targetType Class to cast the operand (function parameter) to. Used only to set the generic type * @param Operand type (type of function parameter) * @param Cast type * * @return The function that will do the cast */ public static Function uncheckedCast(Class targetType) { return (T operand) -> { @SuppressWarnings("unchecked") R castedOperand = (R) operand; return castedOperand; }; } /** * Copy a set, add a value to it and return the new set. * * @param set The original set being copied. * @param value The value being appended to the set. * @param The type of the set * * @return the new set containing the additional value */ public static Set append(Set set, T value) { HashSet result = new HashSet<>(set); result.add(value); return result; } /** * Merge two sets without modifying either. * This method implements {@link BinaryOperator} for use in stream reductions. * * @param a One input set * @param b Another input set * @param The type of the underlying sets * * @return A new set containing the values of the original sets */ public static Set setMerge(Set a, Set b) { return Stream.concat(a.stream(), b.stream()).collect(Collectors.toSet()); } /** * Merge two sets without modifying either, preserving order. * This method implements {@link BinaryOperator} for use in stream reductions. * * @param a One input set * @param b Another input set * @param The type of the underlying sets * * @return A new set containing the values of the original sets */ public static LinkedHashSet orderedSetMerge(Set a, Set b) { return Stream.concat(a.stream(), b.stream()).collect(Collectors.toCollection(LinkedHashSet::new)); } }