Class BiStream<K,V>

java.lang.Object
com.google.mu.util.stream.BiStream<K,V>
All Implemented Interfaces:
AutoCloseable

public abstract class BiStream<K,V> extends Object implements AutoCloseable
A class similar to Stream, but operating over a sequence of pairs of objects.

Note: For ease of reference, this class uses 'key' and 'value' to refer to each of the two parts of each pair in the sequence. However, both 'key' and 'value' can be any object of the appropriate type, or null. There is no implication that keys or key-value pairs are unique, or that keys can be compared for equality. You may equivalently read them as 'left' and 'right', or 'first' and 'second'.

If the contents of the stream aren't identifiably 'keys' or 'values', and the methods with 'key' or 'value' in their name are distracting, consider using the pair-wise operations. For instance, instead of:


 BiStream.from(cities.stream(), City::population, City::latitude)
     .filterKeys(p -> p > 10000);
 
you might use:

 BiStream.from(cities.stream(), City::population, City::latitude)
     .filter((population, lat) -> population > 10000);
 

Keys and values are allowed to be null by default unless explicitly documented otherwise.

Some methods (e.g. mapKeys()) come in two versions, one taking BiFunction (which will receive both key and value) and another taking Function (which in this case will receive only the key) . They operate equivalently otherwise.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final class 
    Builder for BiStream.
    static interface 
    A predicate used to partition a BiStream into sub-groups of consecutive pairs.
  • Method Summary

    Modifier and Type
    Method
    Description
    abstract boolean
    allMatch(BiPredicate<? super K,? super V> predicate)
    Returns true if all pairs in this stream match predicate.
    abstract boolean
    anyMatch(BiPredicate<? super K,? super V> predicate)
    Returns true if any pair in this stream matches predicate.
    final BiStream<K,V>
    append(BiStream<? extends K,? extends V> other)
    Returns a BiStream consisting of the pairs in this stream, followed by the pairs in other.
    final BiStream<K,V>
    append(K key, V value)
    Returns a BiStream consisting of the pairs in this stream, followed by the pair of key and value.
    static <K, V> BiStream<K,V>
    biStream(Collection<K> keys, Function<? super K,? extends V> toValue)
    Returns a BiStream of mappings between keys and the corresponding return values of the toValue function.
    static <T> BiStream<T,T>
    biStream(Collection<T> elements)
    Short-hand for from(elements, identity(), identity()).
    static <K, V> BiStream<K,V>
    biStream(Function<? super V,? extends K> toKey, Collection<V> values)
    Returns a BiStream of mappings between the key returned by the toKey function (when applied to each element of values), and the element itself.
    static <K, V> BiStream<K,V>
    biStream(Function<? super V,? extends K> toKey, Stream<V> values)
    Returns a BiStream of mappings between the key returned by the toKey function (when applied to each element of values), and the element itself.
    static <K, V> BiStream<K,V>
    biStream(Stream<K> keys, Function<? super K,? extends V> toValue)
    Returns a BiStream of mappings between keys and the corresponding return values of the toValue function.
    static <T> BiStream<T,T>
    biStream(Stream<T> elements)
    Short-hand for from(elements, identity(), identity()).
    static <K, V> BiStream.Builder<K,V>
    Returns a new BiStream.Builder.
    abstract void
    Closes any resources associated with this stream, typically used in a try-with-resources statement.
    abstract <A> A
    collect(A container, BiAccumulator<? super A,? super K,? super V> accumulator)
    Performs mutable reduction, as in collect(ImmutableMap.builder(), ImmutableMap.Builder::put).
    abstract <R> R
    collect(BiCollector<? super K,? super V,R> collector)
    Returns an object of type R that is the result of collecting the pairs in this stream using collector.
    final <T, R> R
    collect(BiCollector<? super K,? super V,T> collector, Function<? super T,R> finisher)
    Equivalent to collect(collectingAndThen(collector, finisher)) but helps to save syntactic noise.
    static <K, V> BiStream<K,V>
    concat(BiStream<? extends K,? extends V> s1, BiStream<? extends K,? extends V> s2, BiStream<? extends K,? extends V>... rest)
    Returns a BiStream of the entries from s1, s2 then rest in encounter order.
    static <K, V> BiStream<K,V>
    concat(Map<? extends K,? extends V> m1, Map<? extends K,? extends V> m2, Map<? extends K,? extends V>... rest)
    Returns a BiStream of the entries from m1, m2 then rest in encounter order.
    static <K, V> BiStream<K,V>
    concat(Stream<? extends BiStream<? extends K,? extends V>> biStreams)
    Returns a BiStream of pairs from biStreams concatenated in encounter order.
    static <T, K, V> Collector<T,?,BiStream<K,V>>
    concatenating(Function<? super T,? extends BiStream<? extends K,? extends V>> toBiStream)
    Returns a Collector that concatenates BiStream objects derived from the input elements using the given toBiStream function.
    final long
    Returns the count of pairs in this stream.
    static <L, R> Collector<L,?,BiStream<L,R>>
    crossJoining(Stream<R> right)
    Returns a Collector that will pair each input element with each element from right into a new BiStream.
    final BiStream<K,V>
    Returns a BiStream consisting of only the distinct pairs (according to Object.equals(Object) for both key and value).
    static <K, V> BiStream<K,V>
    Returns an empty BiStream.
    final BiStream<K,V>
    filter(BiPredicate<? super K,? super V> predicate)
    Filter this stream to only pairs matching predicate.
    final BiStream<K,V>
    filterKeys(Predicate<? super K> predicate)
    Filter this stream to only pairs whose key matches predicate.
    final BiStream<K,V>
    filterValues(Predicate<? super V> predicate)
    Filter this stream to only pairs whose value matches predicate.
    final BiOptional<K,V>
    Returns any pair from this stream, or BiOptional.empty() if the stream is empty.
    final BiOptional<K,V>
    Returns the first pair from this stream, or BiOptional.empty() if the stream is empty.
    final <K2, V2> BiStream<K2,V2>
    flatMap(BiFunction<? super K,? super V,? extends BiStream<? extends K2,? extends V2>> mapper)
    Maps each pair in this stream to zero or more pairs in another BiStream.
    final <K2> BiStream<K2,V>
    flatMapKeys(BiFunction<? super K,? super V,? extends Stream<? extends K2>> keyMapper)
    Maps each key to zero or more keys of type K2.
    final <K2> BiStream<K2,V>
    flatMapKeys(Function<? super K,? extends Stream<? extends K2>> keyMapper)
    Maps each key to zero or more keys of type K2.
    flatMapToDouble(BiFunction<? super K,? super V,? extends DoubleStream> mapper)
    Maps a single pair to zero or more doubles.
    final IntStream
    flatMapToInt(BiFunction<? super K,? super V,? extends IntStream> mapper)
    Maps a single pair to zero or more ints.
    flatMapToLong(BiFunction<? super K,? super V,? extends LongStream> mapper)
    Maps a single pair to zero or more longs.
    final <T> Stream<T>
    flatMapToObj(BiFunction<? super K,? super V,? extends Stream<? extends T>> mapper)
    Maps a single pair to zero or more objects of type T.
    final <V2> BiStream<K,V2>
    flatMapValues(BiFunction<? super K,? super V,? extends Stream<? extends V2>> valueMapper)
    Maps each value to zero or more values of type V2.
    final <V2> BiStream<K,V2>
    flatMapValues(Function<? super V,? extends Stream<? extends V2>> valueMapper)
    Maps each value to zero or more values of type V2.
    abstract void
    forEach(BiConsumer<? super K,? super V> action)
    Performs action for each pair in this stream.
    abstract void
    forEachOrdered(BiConsumer<? super K,? super V> consumer)
    Performs action for each pair in this stream, in order.
    static <K, V> BiStream<K,V>
    from(Collection<? extends Map.Entry<? extends K,? extends V>> entries)
    Returns a BiStream of the key value pairs from entries.
    static <T, K, V> BiStream<K,V>
    from(Collection<T> elements, Function<? super T,? extends K> toKey, Function<? super T,? extends V> toValue)
    Deprecated.
    Use biStream(User::id, users) to create BiStream<UserId, User>, or, use biStream(users, User::getAccount) to create BiStream<User, Account>.
    static <K, V> BiStream<K,V>
    from(Map<K,V> map)
    Returns a BiStream of the entries in map.
    static <K, V> BiStream<K,V>
    from(Stream<? extends Both<? extends K,? extends V>> pairs)
    Returns a BiStream of the pairs from stream.
    static <T, K, V> BiStream<K,V>
    from(Stream<T> stream, Function<? super T,? extends K> toKey, Function<? super T,? extends V> toValue)
    Deprecated.
    Use biStream(User::id, users) to create BiStream<UserId, User>, or, use biStream(users, User::getAccount) to create BiStream<User, Account>.
    static <K, V, E extends Map.Entry<? extends K, ? extends V>>
    BiStream<K,V>
    fromEntries(Stream<E> entryStream)
     
    final <G, A, R> BiStream<G,R>
    groupConsecutiveBy(BiFunction<? super K,? super V,? extends G> classifier, BiCollector<? super K,? super V,R> groupCollector)
    Returns a BiStream consisting of consecutive groupings from this stream.
    final <G> BiStream<G,V>
    groupConsecutiveBy(Function<? super K,? extends G> classifier, BinaryOperator<V> groupReducer)
    Returns a lazy BiStream of the consecutive groups of pairs from this stream.
    final <G, A, R> BiStream<G,R>
    groupConsecutiveBy(Function<? super K,? extends G> classifier, Collector<? super V,A,? extends R> groupCollector)
    Returns a BiStream consisting of consecutive groupings from this stream.
    final <R> Stream<R>
    groupConsecutiveIf(BiStream.Partitioner<? super K,? super V> sameGroup, BiCollector<? super K,? super V,R> groupCollector)
    Returns a lazy Stream of the consecutive groups of values from this stream.
    final Stream<V>
    groupConsecutiveIf(BiPredicate<? super K,? super K> sameGroup, BinaryOperator<V> groupReducer)
    Returns a lazy Stream of the consecutive groups of values from this stream.
    final <A, R> Stream<R>
    groupConsecutiveIf(BiPredicate<? super K,? super K> sameGroup, Collector<? super V,A,R> groupCollector)
    Returns a lazy Stream of the consecutive groups of values from this stream.
    static <T, K> Collector<T,?,BiStream<K,List<T>>>
    groupingBy(Function<? super T,? extends K> classifier)
    Returns a Collector that groups the input elements by classifier and collects the values mapping to the same key into a List.
    static <T, K, V> Collector<T,?,BiStream<K,V>>
    groupingBy(Function<? super T,? extends K> classifier, Function<? super T,? extends V> mapper, BinaryOperator<V> reducer)
    Returns a Collector that groups the input elements by classifier and reduces the values mapping to the same key using mapper then reducer.
    static <T, K, V> Collector<T,?,BiStream<K,V>>
    groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,?,V> valueCollector)
    Returns a Collector that groups the input elements by classifier and collects the values mapping to the same key using valueCollector.
    static <K, V> Collector<V,?,BiStream<K,V>>
    groupingBy(Function<? super V,? extends K> classifier, BinaryOperator<V> reducer)
    Returns a Collector that groups the input elements by classifier and reduces the values mapping to the same key using reducer.
    static <T, K, V> Collector<T,?,BiStream<K,V>>
    groupingByEach(Function<? super T,? extends Stream<? extends K>> keysFunction, Function<? super T,? extends V> valueFunction, BinaryOperator<V> groupReducer)
    Returns a Collector grouping input elements by each of the multiple keys returned by the keysFunction.
    static <T, K, V, G>
    Collector<T,?,BiStream<K,G>>
    groupingByEach(Function<? super T,? extends Stream<? extends K>> keysFunction, Function<? super T,? extends V> valueFunction, Collector<V,?,G> groupCollector)
    Returns a Collector grouping input elements by each of the multiple keys returned by the keysFunction.
    static <T, K, V> Collector<T,?,BiStream<K,V>>
    groupingByEach(Function<? super T,? extends Stream<? extends K>> keysFunction, Collector<T,?,V> groupCollector)
    Returns a Collector grouping input elements by each of the multiple keys returned by the keysFunction.
    abstract BiStream<V,K>
    Returns a BiStream where each pair is a pair from this stream with the key and value swapped.
    final Stream<K>
    Returns a Stream consisting of only the keys from each pair in this stream.
    abstract BiStream<K,V>
    limit(int maxSize)
    Returns a BiStream consisting of the only the first maxSize pairs of this stream.
    final <K2, V2> BiStream<K2,V2>
    map(BiFunction<? super K,? super V,? extends Both<? extends K2,? extends V2>> mapper)
    Returns a BiStream consisting of the result pairs of applying mapper to the pairs in this BiStream.
    <K2, V2> BiStream<K2,V2>
    map(BiFunction<? super K,? super V,? extends K2> keyMapper, BiFunction<? super K,? super V,? extends V2> valueMapper)
    Returns a BiStream consisting of the results of applying keyMapper and valueMapper to the pairs in this BiStream.
    final <K2, V2> BiStream<K2,V2>
    mapIfPresent(BiFunction<? super K,? super V,? extends BiOptional<? extends K2,? extends V2>> mapper)
    Returns a BiStream consisting of the results of applying mapper function to the pairs in this BiStream.
    <K2> BiStream<K2,V>
    mapKeys(BiFunction<? super K,? super V,? extends K2> keyMapper)
    Returns a BiStream of pairs whose keys are the result of applying keyMapper to the key of each pair in this BiStream, and whose values are unchanged.
    abstract <K2> BiStream<K2,V>
    mapKeys(Function<? super K,? extends K2> keyMapper)
    Maps each key to another key of type K2.
    final <K2> BiStream<K2,V>
    mapKeysIfPresent(BiFunction<? super K,? super V,? extends Optional<? extends K2>> keyMapper)
    Returns a BiStream of pairs whose keys are the result of applying keyMapper to each pair in this BiStream, and whose values are unchanged.
    final <K2> BiStream<K2,V>
    mapKeysIfPresent(Function<? super K,? extends Optional<? extends K2>> keyMapper)
    Returns a BiStream of pairs whose keys are the result of applying keyMapper to the key of each pair in this BiStream, and whose values are unchanged.
    final <K2> BiStream<K2,V>
    mapKeysIfPresent(Map<? super K,? extends K2> keyMapping)
    Given keyMapping that maps the keys of type K to elements of type K2, returns a BiStream of type <K2, V>.
    abstract DoubleStream
    mapToDouble(ToDoubleBiFunction<? super K,? super V> mapper)
    Returns a DoubleStream consisting of the results of applying mapper to the pairs in this BiStream.
    abstract IntStream
    mapToInt(ToIntBiFunction<? super K,? super V> mapper)
    Returns an IntStream consisting of the results of applying mapper to the pairs in this BiStream.
    abstract LongStream
    mapToLong(ToLongBiFunction<? super K,? super V> mapper)
    Returns a LongStream consisting of the results of applying mapper to the pairs in this BiStream.
    abstract <T> Stream<T>
    mapToObj(BiFunction<? super K,? super V,? extends T> mapper)
    Returns a Stream consisting of the results of applying mapper to each pair in this BiStream.
    final <T> Stream<T>
    mapToObjIfPresent(BiFunction<? super K,? super V,? extends Optional<? extends T>> mapper)
    Returns a Stream consisting of the results of applying mapper to each pair in this BiStream.
    <V2> BiStream<K,V2>
    mapValues(BiFunction<? super K,? super V,? extends V2> valueMapper)
    Maps each value to another value of type V2.
    abstract <V2> BiStream<K,V2>
    mapValues(Function<? super V,? extends V2> valueMapper)
    Maps each value to another value of type V2.
    final <V2> BiStream<K,V2>
    mapValuesIfPresent(BiFunction<? super K,? super V,? extends Optional<? extends V2>> valueMapper)
    Returns a BiStream of pairs whose values are the result of applying valueMapper to each pair in this BiStream, and whose keys are unchanged.
    final <V2> BiStream<K,V2>
    mapValuesIfPresent(Function<? super V,? extends Optional<? extends V2>> valueMapper)
    Returns a BiStream of pairs whose values are the result of applying valueMapper to the value of each pair in this BiStream, and whose keys are unchanged.
    final <V2> BiStream<K,V2>
    mapValuesIfPresent(Map<? super V,? extends V2> valueMapping)
    Given valueMapping that maps values of type V to result values of type V2, returns a BiStream of type <K, V2>.
    final boolean
    noneMatch(BiPredicate<? super K,? super V> predicate)
    Returns true if no pairs in this stream match predicate.
    static <K, V> BiStream<K,V>
    of(K key, V value)
    Returns a BiStream of a single pair containing key and value.
    static <K, V> BiStream<K,V>
    of(K key1, V value1, K key2, V value2)
    Returns a BiStream of two pairs, containing the supplied keys and values.
    static <K, V> BiStream<K,V>
    of(K key1, V value1, K key2, V value2, K key3, V value3)
    Returns a BiStream of three pairs, containing the supplied keys and values.
    static <K, V> BiStream<K,V>
    of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4)
    Returns a BiStream of 4 pairs, containing the supplied keys and values.
    static <K, V> BiStream<K,V>
    of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5)
    Returns a BiStream of 5 pairs, containing the supplied keys and values.
    static <K, V> BiStream<K,V>
    of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6)
    Returns a BiStream of 6 pairs, containing the supplied keys and values.
    static <K, V> BiStream<K,V>
    of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7)
    Returns a BiStream of 7 pairs, containing the supplied keys and values.
    static <K, V> BiStream<K,V>
    of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8)
    Returns a BiStream of 8 pairs, containing the supplied keys and values.
    static <K, V> BiStream<K,V>
    of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9)
    Returns a BiStream of 9 pairs, containing the supplied keys and values.
    static <K, V> BiStream<K,V>
    of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10)
    Returns a BiStream of 10 pairs, containing the supplied keys and values.
    final BiStream<K,V>
    peek(BiConsumer<? super K,? super V> action)
    Returns a BiStream consisting of the pairs of this stream, additionally invoking action on each pair as pairs are consumed from the resulting stream.
    static <I, O> BiStream<I,O>
    repeat(Function<? super I,? extends O> work, I initial, BiFunction<? super I,? super O,? extends Optional<? extends I>> increment)
    Returns a stream of the inputs and outputs from repeated applications of the work function.
    abstract BiStream<K,V>
    skip(int n)
    Returns a BiStream consisting of the remaining pairs from this stream, after discarding the first n pairs.
    final BiStream<K,V>
    skipIf(BiPredicate<? super K,? super V> predicate)
    Filter this stream to exclude pairs matching predicate.
    final BiStream<K,V>
    skipKeysIf(Predicate<? super K> predicate)
    Filter this stream to exclude pairs whose key matches predicate.
    final BiStream<K,V>
    skipValuesIf(Predicate<? super V> predicate)
    Filter this stream to exclude pairs whose value matches predicate.
    final BiStream<K,V>
    sorted(Comparator<? super K> byKey, Comparator<? super V> byValue)
    Returns a BiStream consisting of the pairs in this stream, in the order produced by applying the byKey comparator on the keys of each pair, and then the byValue comparator on the values of pairs with equal keys.
    final <T> BiStream<K,V>
    sortedBy(BiFunction<? super K,? super V,T> sortKeyFunction, Comparator<? super T> comparator)
    Returns a BiStream consisting of the pairs in this stream, in the order produced by applying comparator on the result of applying the sortKeyFunction.
    final BiStream<K,V>
    sortedByKeys(Comparator<? super K> comparator)
    Returns a BiStream consisting of the pairs in this stream, in the order produced by applying comparator on the keys of each pair.
    final BiStream<K,V>
    sortedByValues(Comparator<? super V> comparator)
    Returns a BiStream consisting of the pairs in this stream, in the order produced by applying comparator on the values of each pair.
    static <T> Collector<T,?,BiStream<T,T>>
    Returns a Collector that accumulates every neighboring pair of elements into a new BiStream.
    static <T> Collector<T,?,BiStream<T,T>>
    Returns a Collector that copies each input element as a pair of itself into an equivalent BiStream.
    static <E, K, V> Collector<E,?,BiStream<K,V>>
    toBiStream(Function<? super E,? extends Both<? extends K,? extends V>> toPair)
    Returns a Collector that splits each input element as a pair and collects them into a BiStream.
    static <E, K, V> Collector<E,?,BiStream<K,V>>
    toBiStream(Function<? super E,? extends K> toKey, Function<? super E,? extends V> toValue)
    Returns a Collector that splits each input element as a pair and collects them into a BiStream.
    final Map<K,V>
    Returns an immutable Map that is the result of collecting the pairs in this stream.
    final Stream<V>
    Returns a Stream consisting of only the values from each pair in this stream.
    static <L, R> BiStream<L,R>
    zip(Collection<L> left, Collection<R> right)
    Returns a BiStream in which the first element in left is paired with the first element in right; the second paired with the corresponding second and the third with the corresponding third etc.
    static <L, R> BiStream<L,R>
    zip(Stream<L> left, Stream<R> right)
    Returns a BiStream in which the first element in left is paired with the first element in right; the second paired with the corresponding second and the third with the corresponding third etc.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • builder

      public static <K, V> BiStream.Builder<K,V> builder()
      Returns a new BiStream.Builder.
      Since:
      3.2
    • groupingBy

      public static <K, V> Collector<V,?,BiStream<K,V>> groupingBy(Function<? super V,? extends K> classifier, BinaryOperator<V> reducer)
      Returns a Collector that groups the input elements by classifier and reduces the values mapping to the same key using reducer.
      
       ImmutableMap<CurrencyCode, Money> expenseByCurrency = expenses.stream()
           .collect(groupingBy(Money::currencyCode, Money::add))
           .collect(ImmutableMap::toImmutableMap);
       

      Entries are collected in encounter order.

      Since:
      3.3
    • groupingBy

      public static <T, K, V> Collector<T,?,BiStream<K,V>> groupingBy(Function<? super T,? extends K> classifier, Function<? super T,? extends V> mapper, BinaryOperator<V> reducer)
      Returns a Collector that groups the input elements by classifier and reduces the values mapping to the same key using mapper then reducer.
      
       ImmutableMap<State, Money> householdIncomeByState = households.stream()
           .collect(groupingBy(Household::state, Household::income, Money::add))
           .collect(ImmutableMap::toImmutableMap);
       

      Entries are collected in encounter order.

      Since:
      3.3
    • groupingBy

      public static <T, K> Collector<T,?,BiStream<K,List<T>>> groupingBy(Function<? super T,? extends K> classifier)
      Returns a Collector that groups the input elements by classifier and collects the values mapping to the same key into a List. Similar but different from Collectors.groupingBy(Function), this method collects the groups into BiStream() instead, allowing fluent method chaining. For example:
      
       Map<EmployeeId, List<Task>> employeesWithMultipleTasks = tasks.stream()
           .collect(BiStream.groupingBy(Task::assignedTo))
           .filterValues(tasks -> tasks.size() > 1)
           .toMap();
       
      Even if you don't need to chain more methods, using this collector allows you to fluently collect the results into the desired container type. For example toMap() collects to an immutable Map; or collect(Collectors::toConcurrentMap) if concurrency is needed.

      Entries are collected in encounter order.

      Since:
      3.0
    • groupingBy

      public static <T, K, V> Collector<T,?,BiStream<K,V>> groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,?,V> valueCollector)
      Returns a Collector that groups the input elements by classifier and collects the values mapping to the same key using valueCollector. Similar but different from Collectors.groupingBy(Function, Collector), this method collects the groups into BiStream() instead, allowing fluent method chaining. For example:
      
       Map<EmployeeId, Integer> topTenEmployeesByWorkHour = projects.stream()
           .flatMap(project -> project.getMembers().stream())  // Stream<TeamMember>
           .collect(BiStream.groupingBy(TeamMember::employeeId, summingInt(TeamMember::hours)))
           .sortedByValues(Comparator.reverseOrder())
           .limit(10)
           .toMap();
       
      Even if you don't need to chain more methods, using this collector allows you to fluently collect the results into the desired container type. For example toMap() collects to an immutable Map; or you could supply collect(ImmutableBiMap::toImmutableBiMap) if BiMap is needed.

      Entries are collected in encounter order.

      Since:
      3.0
    • groupingByEach

      public static <T, K, V> Collector<T,?,BiStream<K,V>> groupingByEach(Function<? super T,? extends Stream<? extends K>> keysFunction, Collector<T,?,V> groupCollector)
      Returns a Collector grouping input elements by each of the multiple keys returned by the keysFunction. It's similar to groupingBy(Function, Collector) except each element can belong to multiple groups. For example:
      
       ImmutableMap<Person, ImmutableList<Club>> clubMemberships =
           clubs.stream()
               .collect(
                   groupingByEach(club -> club.getMembers().stream(), toImmutableList()))
               .toMap();
       

      Entries are collected in encounter order.

      Since:
      6.5
    • groupingByEach

      public static <T, K, V, G> Collector<T,?,BiStream<K,G>> groupingByEach(Function<? super T,? extends Stream<? extends K>> keysFunction, Function<? super T,? extends V> valueFunction, Collector<V,?,G> groupCollector)
      Returns a Collector grouping input elements by each of the multiple keys returned by the keysFunction. The input element is passed to the valueFunction and the return value is added to every group it belongs to. And finally each group is collected using groupCollector. For example:
      
       ImmutableMap<EmployeeId, ImmutableList<ProjectId>> projectIdsPerEmployee =
           projects.stream()
               .collect(
                   groupingByEach(
                       project -> project.getOwnersList().stream(),
                       Project::id,
                       toImmutableList()))
               .toMap();
       

      Entries are collected in encounter order.

      Since:
      6.5
    • groupingByEach

      public static <T, K, V> Collector<T,?,BiStream<K,V>> groupingByEach(Function<? super T,? extends Stream<? extends K>> keysFunction, Function<? super T,? extends V> valueFunction, BinaryOperator<V> groupReducer)
      Returns a Collector grouping input elements by each of the multiple keys returned by the keysFunction. It's similar to groupingBy(Function, Function, BinaryOperator) except each element can belong to multiple groups. For example:
      
       ImmutableMap<Person, Money> clubMembershipFees =
           clubs.stream()
               .collect(
                   groupingByEach(
                       club -> club.getMembers().stream(),
                       Club::getMembershipFee,
                       Money::add))
               .toMap();
       

      Entries are collected in encounter order.

      Since:
      6.5
    • concatenating

      public static <T, K, V> Collector<T,?,BiStream<K,V>> concatenating(Function<? super T,? extends BiStream<? extends K,? extends V>> toBiStream)
      Returns a Collector that concatenates BiStream objects derived from the input elements using the given toBiStream function.

      For example:

      
       Map<EmployeeId, Task> billableTaskAssignments = projects.stream()
           .collect(concatenating(p -> BiStream.from(p.getTaskAssignments())))
           .filterValues(Task::billable)
           .toMap();
       
      Since:
      3.0
    • crossJoining

      public static <L, R> Collector<L,?,BiStream<L,R>> crossJoining(Stream<R> right)
      Returns a Collector that will pair each input element with each element from right into a new BiStream. For example:
      
       ImmutableList<QuarterlyReport> allQuarterlyReports = quarters.stream()
           .collect(crossJoining(departments))
           .mapToObj(QuarterlyReport::new)
           .collect(toImmutableList());
       

      The input elements are repeated once per element from right. For example: [1, 2, 3].collect(crossJoining([a, b])) will generate [{1, a}, {2, a}, {3, a}, {1, b}, {2, b}, {3, b}].

      The returned BiStream takes O(n) space where n is the size of the input elements. The "cross-joining" with the right stream is computed on-the-fly with O(1) memory cost.

      Since:
      3.0
    • toAdjacentPairs

      public static <T> Collector<T,?,BiStream<T,T>> toAdjacentPairs()
      Returns a Collector that accumulates every neighboring pair of elements into a new BiStream. For example Stream.of(1, 2, 3, 4).collect(toAdjacentPairs()) will return [{1, 2}, {2, 3}, {3, 4}].

      If the input has 0 or 1 elements then the output is an empty BiStream. Otherwise the length of the output BiStream is one less than the length of the input.

      Since:
      3.2
    • toBiStream

      public static <E, K, V> Collector<E,?,BiStream<K,V>> toBiStream(Function<? super E,? extends K> toKey, Function<? super E,? extends V> toValue)
      Returns a Collector that splits each input element as a pair and collects them into a BiStream.

      Note that it's more efficient to use BiStream.from(stream, toKey, toValue) than stream.collect(toBiStream(toKey, toValue)). The latter is intended to be used in the middle of a long stream pipeline, when performance isn't critical.

      Since:
      3.2
    • toBiStream

      public static <E, K, V> Collector<E,?,BiStream<K,V>> toBiStream(Function<? super E,? extends Both<? extends K,? extends V>> toPair)
      Returns a Collector that splits each input element as a pair and collects them into a BiStream.

      Note that it's more efficient to use BiStream.from(stream, toPair) than stream.collect(toBiStream(toPair)). The latter is intended to be used in the middle of a long stream pipeline, when performance isn't critical.

      Since:
      5.1
    • toBiStream

      public static <T> Collector<T,?,BiStream<T,T>> toBiStream()
      Returns a Collector that copies each input element as a pair of itself into an equivalent BiStream.

      Note that it's more efficient to use biStream(stream) than stream.collect(toBiStream()). The latter is intended to be used in the middle of a long stream pipeline, when performance isn't critical.

      Since:
      3.6
    • empty

      public static <K, V> BiStream<K,V> empty()
      Returns an empty BiStream.
    • of

      public static <K, V> BiStream<K,V> of(K key, V value)
      Returns a BiStream of a single pair containing key and value.
    • of

      public static <K, V> BiStream<K,V> of(K key1, V value1, K key2, V value2)
      Returns a BiStream of two pairs, containing the supplied keys and values.
    • of

      public static <K, V> BiStream<K,V> of(K key1, V value1, K key2, V value2, K key3, V value3)
      Returns a BiStream of three pairs, containing the supplied keys and values.
    • of

      public static <K, V> BiStream<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4)
      Returns a BiStream of 4 pairs, containing the supplied keys and values.
      Since:
      5.6
    • of

      public static <K, V> BiStream<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5)
      Returns a BiStream of 5 pairs, containing the supplied keys and values.
      Since:
      5.6
    • of

      public static <K, V> BiStream<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6)
      Returns a BiStream of 6 pairs, containing the supplied keys and values.
      Since:
      5.6
    • of

      public static <K, V> BiStream<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7)
      Returns a BiStream of 7 pairs, containing the supplied keys and values.
      Since:
      5.6
    • of

      public static <K, V> BiStream<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8)
      Returns a BiStream of 8 pairs, containing the supplied keys and values.
      Since:
      5.6
    • of

      public static <K, V> BiStream<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9)
      Returns a BiStream of 9 pairs, containing the supplied keys and values.
      Since:
      5.6
    • of

      public static <K, V> BiStream<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10)
      Returns a BiStream of 10 pairs, containing the supplied keys and values.
      Since:
      5.6
    • concat

      @SafeVarargs public static <K, V> BiStream<K,V> concat(Map<? extends K,? extends V> m1, Map<? extends K,? extends V> m2, Map<? extends K,? extends V>... rest)
      Returns a BiStream of the entries from m1, m2 then rest in encounter order. For example:
      
       Map<AccountId, Account> allAccounts = concat(primaryAccounts, secondaryAccounts).toMap();
       
      Since:
      3.0
    • concat

      @SafeVarargs public static <K, V> BiStream<K,V> concat(BiStream<? extends K,? extends V> s1, BiStream<? extends K,? extends V> s2, BiStream<? extends K,? extends V>... rest)
      Returns a BiStream of the entries from s1, s2 then rest in encounter order. For example:
      
       Map<AccountId, Account> allAccounts = concat(primaryAccounts, secondaryAccounts).toMap();
       
      Since:
      4.7
    • concat

      public static <K, V> BiStream<K,V> concat(Stream<? extends BiStream<? extends K,? extends V>> biStreams)
      Returns a BiStream of pairs from biStreams concatenated in encounter order.
      Since:
      3.0
    • zip

      public static <L, R> BiStream<L,R> zip(Collection<L> left, Collection<R> right)
      Returns a BiStream in which the first element in left is paired with the first element in right; the second paired with the corresponding second and the third with the corresponding third etc. For example: BiStream.zip(asList(1, 2, 3), asList("one", "two")) will return BiStream.of(1, "one", 2, "two").

      The resulting stream will only be as long as the shorter of the two iterables; if one is longer, its extra elements will be ignored.

      Since:
      3.0
    • zip

      public static <L, R> BiStream<L,R> zip(Stream<L> left, Stream<R> right)
      Returns a BiStream in which the first element in left is paired with the first element in right; the second paired with the corresponding second and the third with the corresponding third etc. For example: BiStream.zip(Stream.of(1, 2, 3), Stream.of("one", "two")) will return BiStream.of(1, "one", 2, "two").

      The resulting stream will only be as long as the shorter of the two input streams; if one stream is longer, its extra elements will be ignored.

      The resulting stream by default runs sequentially regardless of the input streams. This is because the implementation is not efficiently splittable. and may not perform well if run in parallel.

    • biStream

      public static <T> BiStream<T,T> biStream(Collection<T> elements)
      Short-hand for from(elements, identity(), identity()). Typically followed by mapKeys(java.util.function.BiFunction<? super K, ? super V, ? extends K2>) or mapValues(java.util.function.BiFunction<? super K, ? super V, ? extends V2>). For example:
      
       static import com.google.common.labs.collect.BiStream.biStream;
      
       Map<EmployeeId, Employee> employeesById = biStream(employees)
           .mapKeys(Employee::id)
           .toMap();
       
      Since:
      3.0
    • biStream

      public static <T> BiStream<T,T> biStream(Stream<T> elements)
      Short-hand for from(elements, identity(), identity()). Typically followed by mapKeys(java.util.function.BiFunction<? super K, ? super V, ? extends K2>) or mapValues(java.util.function.BiFunction<? super K, ? super V, ? extends V2>). For example:
      
       static import com.google.common.labs.collect.BiStream.biStream;
      
       Map<EmployeeId, Employee> employeesById = biStream(employees)
           .mapKeys(Employee::id)
           .toMap();
       
      Since:
      3.6
    • biStream

      public static <K, V> BiStream<K,V> biStream(Collection<K> keys, Function<? super K,? extends V> toValue)
      Returns a BiStream of mappings between keys and the corresponding return values of the toValue function. For example:
      
       BiStream<Request, ListenableFuture<Response>> requestsAndResponses =
           biStream(requests, service::sendRequest);
       
      Since:
      5.6
    • biStream

      public static <K, V> BiStream<K,V> biStream(Stream<K> keys, Function<? super K,? extends V> toValue)
      Returns a BiStream of mappings between keys and the corresponding return values of the toValue function. For example:
      
       BiStream<Request, ListenableFuture<Response>> requestsAndResponses =
           biStream(requests, service::sendRequest);
       
      Since:
      5.6
    • biStream

      public static <K, V> BiStream<K,V> biStream(Function<? super V,? extends K> toKey, Collection<V> values)
      Returns a BiStream of mappings between the key returned by the toKey function (when applied to each element of values), and the element itself.
      
       ImmutableListMultimap<UserId, Account> userAccounts =
           biStream(User::id, users)
               .flatMapValues(User::accounts)
               .collect(toImmutableListMultimap());
       
      Since:
      5.6
    • biStream

      public static <K, V> BiStream<K,V> biStream(Function<? super V,? extends K> toKey, Stream<V> values)
      Returns a BiStream of mappings between the key returned by the toKey function (when applied to each element of values), and the element itself.
      
       ImmutableListMultimap<UserId, Account> userAccounts =
           biStream(User::id, users)
               .flatMapValues(User::accounts)
               .collect(toImmutableListMultimap());
       
      Since:
      5.6
    • from

      public static <K, V> BiStream<K,V> from(Map<K,V> map)
      Returns a BiStream of the entries in map.
    • from

      public static <K, V> BiStream<K,V> from(Collection<? extends Map.Entry<? extends K,? extends V>> entries)
      Returns a BiStream of the key value pairs from entries. For example BiStream.from(multimap.entries()).
      Since:
      4.7
    • from

      @Deprecated public static <T, K, V> BiStream<K,V> from(Collection<T> elements, Function<? super T,? extends K> toKey, Function<? super T,? extends V> toValue)
      Deprecated.
      Use biStream(User::id, users) to create BiStream<UserId, User>, or, use biStream(users, User::getAccount) to create BiStream<User, Account>. Then use mapKeys(java.util.function.BiFunction<? super K, ? super V, ? extends K2>) or mapValues(java.util.function.BiFunction<? super K, ? super V, ? extends V2>) to apply further mappings.
      Returns a BiStream of elements, each transformed to a pair of values with toKey and toValue.
    • from

      @Deprecated public static <T, K, V> BiStream<K,V> from(Stream<T> stream, Function<? super T,? extends K> toKey, Function<? super T,? extends V> toValue)
      Deprecated.
      Use biStream(User::id, users) to create BiStream<UserId, User>, or, use biStream(users, User::getAccount) to create BiStream<User, Account>. Then use mapKeys(java.util.function.BiFunction<? super K, ? super V, ? extends K2>) or mapValues(java.util.function.BiFunction<? super K, ? super V, ? extends V2>) to apply further mappings.
      Returns a BiStream of the elements from stream, each transformed to a pair of values with toKey and toValue.
    • from

      public static <K, V> BiStream<K,V> from(Stream<? extends Both<? extends K,? extends V>> pairs)
      Returns a BiStream of the pairs from stream.
      Since:
      5.1
    • repeat

      public static <I, O> BiStream<I,O> repeat(Function<? super I,? extends O> work, I initial, BiFunction<? super I,? super O,? extends Optional<? extends I>> increment)
      Returns a stream of the inputs and outputs from repeated applications of the work function. The initial input is passed to work for the first round, after which the increment function is called to determine the input for the next round. This process repeats until the increment function returns Optional.empty().

      A common use case is pagination. For example, if you have a list API with pagination support, the following code retrieves all pages eagerly:

      
       ImmutableList<Foo> listAllFoos() {
         ImmutableList.Builder<Foo> builder = ImmutableList.builder();
         ListFooRequest.Builder request = ListFooRequest.newBuilder()...;
           do {
             ListFooResponse response = service.listFoos(request.build());
             builder.addAll(response.getFoos());
             request.setPageToken(response.getNextPageToken());
           } while (!request.getPageToken().isEmpty());
         return builder.build();
       }
       
      You can turn the above code to a lazy stream so that callers can short-circuit when they need to without having to exhaust all pages:
      
       Stream<Foo> listAllFoos() {
         return BiStream.repeat(
                 service::listFoos,
                 initialRequest,
                 (request, response) ->
                     optional(
                         response.hasNextPageToken(),
                         request.toBuilder().setPageToken(response.getNextPageToken()).build()))
             .flatMapToObj((request, response) -> response.getAllFoos().stream());
       }
       
      Type Parameters:
      I - the input type
      O - the output type
      Parameters:
      work - the function to repeat. Null outputs are passed through as is.
      initial - the initial input to pass to the work function. Cannot be null.
      increment - the function to get the next input given the current input and output.
      Returns:
      A BiStream of the inputs and outputs of the work function. The stream is lazy in that work won't be called until the stream is being consumed; and it won't be called again until the second pair of input and output are being consumed, etc.
      Since:
      5.5
    • fromEntries

      public static <K, V, E extends Map.Entry<? extends K, ? extends V>> BiStream<K,V> fromEntries(Stream<E> entryStream)
      Since:
      7.1
    • mapToObj

      public abstract <T> Stream<T> mapToObj(BiFunction<? super K,? super V,? extends T> mapper)
      Returns a Stream consisting of the results of applying mapper to each pair in this BiStream.
    • mapToObjIfPresent

      public final <T> Stream<T> mapToObjIfPresent(BiFunction<? super K,? super V,? extends Optional<? extends T>> mapper)
      Returns a Stream consisting of the results of applying mapper to each pair in this BiStream. If mapper function returns empty, the pair is discarded.
      Since:
      4.7
    • map

      public <K2, V2> BiStream<K2,V2> map(BiFunction<? super K,? super V,? extends K2> keyMapper, BiFunction<? super K,? super V,? extends V2> valueMapper)
      Returns a BiStream consisting of the results of applying keyMapper and valueMapper to the pairs in this BiStream.
    • map

      public final <K2, V2> BiStream<K2,V2> map(BiFunction<? super K,? super V,? extends Both<? extends K2,? extends V2>> mapper)
      Returns a BiStream consisting of the result pairs of applying mapper to the pairs in this BiStream.

      For example, the following code parses each line read from a file in the format of "key: value", and upon expected format, reports the line number:

      
       import static com.google.mu.util.Substring.first;
      
       BiStream.zip(MoreStreams.indexesFrom(1), readLines().stream())
           .map((lineNumber, line) ->
               first(':')
                   .splitThenTrim(line)
                   .orElseThrow(() -> new IllegalArgumentException("line: " + lineNumber)))
           ...;
       
      Since:
      5.2
    • mapIfPresent

      public final <K2, V2> BiStream<K2,V2> mapIfPresent(BiFunction<? super K,? super V,? extends BiOptional<? extends K2,? extends V2>> mapper)
      Returns a BiStream consisting of the results of applying mapper function to the pairs in this BiStream. If mapper returns empty, the pair is discarded.
      Since:
      5.0
    • mapToDouble

      public abstract DoubleStream mapToDouble(ToDoubleBiFunction<? super K,? super V> mapper)
      Returns a DoubleStream consisting of the results of applying mapper to the pairs in this BiStream.
    • mapToInt

      public abstract IntStream mapToInt(ToIntBiFunction<? super K,? super V> mapper)
      Returns an IntStream consisting of the results of applying mapper to the pairs in this BiStream.
    • mapToLong

      public abstract LongStream mapToLong(ToLongBiFunction<? super K,? super V> mapper)
      Returns a LongStream consisting of the results of applying mapper to the pairs in this BiStream.
    • mapKeys

      public <K2> BiStream<K2,V> mapKeys(BiFunction<? super K,? super V,? extends K2> keyMapper)
      Returns a BiStream of pairs whose keys are the result of applying keyMapper to the key of each pair in this BiStream, and whose values are unchanged.
    • mapKeys

      public abstract <K2> BiStream<K2,V> mapKeys(Function<? super K,? extends K2> keyMapper)
      Maps each key to another key of type K2.
    • mapValues

      public <V2> BiStream<K,V2> mapValues(BiFunction<? super K,? super V,? extends V2> valueMapper)
      Maps each value to another value of type V2.
    • mapValues

      public abstract <V2> BiStream<K,V2> mapValues(Function<? super V,? extends V2> valueMapper)
      Maps each value to another value of type V2.
    • flatMapToObj

      public final <T> Stream<T> flatMapToObj(BiFunction<? super K,? super V,? extends Stream<? extends T>> mapper)
      Maps a single pair to zero or more objects of type T.

      If a mapped stream is null, an empty stream is used instead.

    • flatMapToDouble

      public final DoubleStream flatMapToDouble(BiFunction<? super K,? super V,? extends DoubleStream> mapper)
      Maps a single pair to zero or more doubles.

      If a mapped stream is null, an empty stream is used instead.

    • flatMapToInt

      public final IntStream flatMapToInt(BiFunction<? super K,? super V,? extends IntStream> mapper)
      Maps a single pair to zero or more ints.

      If a mapped stream is null, an empty stream is used instead.

    • flatMapToLong

      public final LongStream flatMapToLong(BiFunction<? super K,? super V,? extends LongStream> mapper)
      Maps a single pair to zero or more longs.

      If a mapped stream is null, an empty stream is used instead.

    • flatMap

      public final <K2, V2> BiStream<K2,V2> flatMap(BiFunction<? super K,? super V,? extends BiStream<? extends K2,? extends V2>> mapper)
      Maps each pair in this stream to zero or more pairs in another BiStream. For example the following code snippet repeats each pair in a BiStream for 3 times:
      
       BiStream<K, V> repeated = stream.flatMap((k, v) -> BiStream.of(k, v, k, v, k, v));
       

      If a mapped stream is null, an empty stream is used instead.

    • flatMapKeys

      public final <K2> BiStream<K2,V> flatMapKeys(BiFunction<? super K,? super V,? extends Stream<? extends K2>> keyMapper)
      Maps each key to zero or more keys of type K2.

      If a mapped stream is null, an empty stream is used instead.

    • flatMapKeys

      public final <K2> BiStream<K2,V> flatMapKeys(Function<? super K,? extends Stream<? extends K2>> keyMapper)
      Maps each key to zero or more keys of type K2.

      If a mapped stream is null, an empty stream is used instead.

    • mapKeysIfPresent

      public final <K2> BiStream<K2,V> mapKeysIfPresent(Map<? super K,? extends K2> keyMapping)
      Given keyMapping that maps the keys of type K to elements of type K2, returns a BiStream of type <K2, V>.

      Keys not found in keyMap (or mapped to null) are discarded.

      For example, if you need to turn a BiStream<StudentId, Score> to BiStream<Student, Score> by looking up the student id in a Map<StudentId, Student>, you can do:

      
       Map<StudentId, Score> scores = ...;
       BiStream.from(scores)
           .mapKeysIfPresent(studentsMap)
           ...;
       

      The above code is equivalent to the following variants:

      
       Map<StudentId, Score> scores = ...;
       BiStream.from(scores)
           .mapKeys(studentsMap::get)
           .mapKeys(Optional::ofNullable)
           .flatMapKeys(Streams::stream)
           ...;
       
      or:
      
       Map<StudentId, Score> scores = ...;
       BiStream.from(scores)
           .mapKeys(studentsMap::get)
           .filterKeys(Objects::nonNull)
           ...;
       
      Since:
      4.7
    • mapKeysIfPresent

      public final <K2> BiStream<K2,V> mapKeysIfPresent(Function<? super K,? extends Optional<? extends K2>> keyMapper)
      Returns a BiStream of pairs whose keys are the result of applying keyMapper to the key of each pair in this BiStream, and whose values are unchanged. If keyMapper function returns empty, the pair is discarded.

      For example the following code counts the total number of unique patients per hospital, from doctors' affiliated hospitals:

      
       Map<Doctor, Patient> doctorAndPatients = ...;
       Map<Hospital, Long> hospitalPatientCounts =
          BiStream.from(doctorAndPatients)
              .mapKeysIfPresent(Doctor::optionalAffliatedHospital)
              .collect(toImmutableMap(counting()));
       
      Since:
      4.7
    • mapKeysIfPresent

      public final <K2> BiStream<K2,V> mapKeysIfPresent(BiFunction<? super K,? super V,? extends Optional<? extends K2>> keyMapper)
      Returns a BiStream of pairs whose keys are the result of applying keyMapper to each pair in this BiStream, and whose values are unchanged. If keyMapper function returns empty, the pair is discarded.
      Since:
      4.7
    • flatMapValues

      public final <V2> BiStream<K,V2> flatMapValues(BiFunction<? super K,? super V,? extends Stream<? extends V2>> valueMapper)
      Maps each value to zero or more values of type V2.

      If a mapped stream is null, an empty stream is used instead.

    • flatMapValues

      public final <V2> BiStream<K,V2> flatMapValues(Function<? super V,? extends Stream<? extends V2>> valueMapper)
      Maps each value to zero or more values of type V2.

      If a mapped stream is null, an empty stream is used instead.

    • mapValuesIfPresent

      public final <V2> BiStream<K,V2> mapValuesIfPresent(Map<? super V,? extends V2> valueMapping)
      Given valueMapping that maps values of type V to result values of type V2, returns a BiStream of type <K, V2>.

      Values not found in valueMap (or mapped to null) are discarded.

      For example, if you need to turn a Multimap<ClassId, StudentId> to Multimap<ClassId, Student> by looking up the student id in a Map<StudentId, Student>, you can do:

      
       Multimap<ClassId, StudentId> registration = ...;
       ImmutableSetMultimap<ClassId, Student> roster = BiStream.from(registration)
           .mapValuesIfPresent(studentsMap)
           .collect(toImmutableSetMultimap());
       

      The above code is equivalent to the following variants:

      
       Multimap<ClassId, StudentId> registration = ...;
       ImmutableSetMultimap<ClassId, Student> roster = BiStream.from(registration)
           .mapValues(studentsMap::get)
           .mapValues(Optional::ofNullable)
           .flatMapValues(Streams::stream)
           .collect(toImmutableSetMultimap());
       
      or:
      
       Multimap<ClassId, StudentId> registration = ...;
       ImmutableSetMultimap<ClassId, Student> roster = BiStream.from(registration)
           .mapValues(studentsMap::get)
           .filterValues(Objects::nonNull)
           .collect(toImmutableSetMultimap());
       
      Since:
      4.7
    • mapValuesIfPresent

      public final <V2> BiStream<K,V2> mapValuesIfPresent(Function<? super V,? extends Optional<? extends V2>> valueMapper)
      Returns a BiStream of pairs whose values are the result of applying valueMapper to the value of each pair in this BiStream, and whose keys are unchanged. If valueMapper function returns empty, the pair is discarded.

      For example the following code collects all unique insurance companies per doctor:

      
       Map<Doctor, Patient> doctorAndPatients = ...;
       ImmutableSetMultimap<Doctor, InsuranceCompany> insurancesPerDoctor =
          BiStream.from(doctorAndPatients)
              .mapValuesIfPresent(Partient::optionalInsurarnce)
              .collect(toImmutableSetMultimap());
       
      Since:
      4.7
    • mapValuesIfPresent

      public final <V2> BiStream<K,V2> mapValuesIfPresent(BiFunction<? super K,? super V,? extends Optional<? extends V2>> valueMapper)
      Returns a BiStream of pairs whose values are the result of applying valueMapper to each pair in this BiStream, and whose keys are unchanged. If valueMapper function returns empty, the pair is discarded.
      Since:
      4.7
    • peek

      public final BiStream<K,V> peek(BiConsumer<? super K,? super V> action)
      Returns a BiStream consisting of the pairs of this stream, additionally invoking action on each pair as pairs are consumed from the resulting stream.
    • filter

      public final BiStream<K,V> filter(BiPredicate<? super K,? super V> predicate)
      Filter this stream to only pairs matching predicate.

      Note that if you are passing in a lambda with the ! operator, consider using skipIf(java.util.function.BiPredicate<? super K, ? super V>) instead that might even allow you to use method reference.

    • filterKeys

      public final BiStream<K,V> filterKeys(Predicate<? super K> predicate)
      Filter this stream to only pairs whose key matches predicate.

      Note that if you are passing in a lambda with the ! operator, consider using skipKeysIf(java.util.function.Predicate<? super K>) instead that might even allow you to use method reference.

    • filterValues

      public final BiStream<K,V> filterValues(Predicate<? super V> predicate)
      Filter this stream to only pairs whose value matches predicate.

      Note that if you are passing in a lambda with the ! operator, consider using skipValuesIf(java.util.function.Predicate<? super V>) instead that might even allow you to use method reference.

    • skipIf

      public final BiStream<K,V> skipIf(BiPredicate<? super K,? super V> predicate)
      Filter this stream to exclude pairs matching predicate.

      Useful especially when it allows you to use method reference. For example:

      
       tasks.stream()
            .collect(crossJoining(Arrays.stream(MachineType.values()))
            .skipIf(Worker::blacklistsMachine)
            ...
       
      Since:
      5.1
    • skipKeysIf

      public final BiStream<K,V> skipKeysIf(Predicate<? super K> predicate)
      Filter this stream to exclude pairs whose key matches predicate.

      Useful especially when it allows you to use method reference. For example:

      
       BiStream.from(rosters)
            .skipKeysIf(inactiveUserIds::contains)
            ...
       
      Since:
      5.1
    • skipValuesIf

      public final BiStream<K,V> skipValuesIf(Predicate<? super V> predicate)
      Filter this stream to exclude pairs whose value matches predicate.

      Useful especially when it allows you to use method reference. For example:

      
       BiStream.zip(userIds, userNames)
            .skipValuesIf(String::isEmpty)
            ...
       
      Since:
      5.1
    • append

      public final BiStream<K,V> append(BiStream<? extends K,? extends V> other)
      Returns a BiStream consisting of the pairs in this stream, followed by the pairs in other.

      NOTE: This method is implemented using Stream.concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>); therefore, the same warnings about deeply-nested combined streams also apply to this method. In particular, avoid calling this method in a loop to combine many streams together.

    • append

      public final BiStream<K,V> append(K key, V value)
      Returns a BiStream consisting of the pairs in this stream, followed by the pair of key and value.

      NOTE: This method is implemented using Stream.concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>); therefore, the same warnings about deeply-nested combined streams also apply to this method. In particular, avoid calling this method in a loop to combine many streams together.

    • keys

      public final Stream<K> keys()
      Returns a Stream consisting of only the keys from each pair in this stream.
    • values

      public final Stream<V> values()
      Returns a Stream consisting of only the values from each pair in this stream.
    • inverse

      public abstract BiStream<V,K> inverse()
      Returns a BiStream where each pair is a pair from this stream with the key and value swapped.
    • forEach

      public abstract void forEach(BiConsumer<? super K,? super V> action)
      Performs action for each pair in this stream.
    • forEachOrdered

      public abstract void forEachOrdered(BiConsumer<? super K,? super V> consumer)
      Performs action for each pair in this stream, in order.
    • allMatch

      public abstract boolean allMatch(BiPredicate<? super K,? super V> predicate)
      Returns true if all pairs in this stream match predicate.
    • anyMatch

      public abstract boolean anyMatch(BiPredicate<? super K,? super V> predicate)
      Returns true if any pair in this stream matches predicate.
    • noneMatch

      public final boolean noneMatch(BiPredicate<? super K,? super V> predicate)
      Returns true if no pairs in this stream match predicate.
    • findFirst

      public final BiOptional<K,V> findFirst()
      Returns the first pair from this stream, or BiOptional.empty() if the stream is empty.
      Throws:
      NullPointerException - if the chosen pair includes null
      Since:
      5.0
    • findAny

      public final BiOptional<K,V> findAny()
      Returns any pair from this stream, or BiOptional.empty() if the stream is empty.
      Throws:
      NullPointerException - if the chosen pair includes null
      Since:
      5.0
    • limit

      public abstract BiStream<K,V> limit(int maxSize)
      Returns a BiStream consisting of the only the first maxSize pairs of this stream.
    • skip

      public abstract BiStream<K,V> skip(int n)
      Returns a BiStream consisting of the remaining pairs from this stream, after discarding the first n pairs.
    • distinct

      public final BiStream<K,V> distinct()
      Returns a BiStream consisting of only the distinct pairs (according to Object.equals(Object) for both key and value).
    • sortedByKeys

      public final BiStream<K,V> sortedByKeys(Comparator<? super K> comparator)
      Returns a BiStream consisting of the pairs in this stream, in the order produced by applying comparator on the keys of each pair.
    • sortedByValues

      public final BiStream<K,V> sortedByValues(Comparator<? super V> comparator)
      Returns a BiStream consisting of the pairs in this stream, in the order produced by applying comparator on the values of each pair.
    • sortedBy

      public final <T> BiStream<K,V> sortedBy(BiFunction<? super K,? super V,T> sortKeyFunction, Comparator<? super T> comparator)
      Returns a BiStream consisting of the pairs in this stream, in the order produced by applying comparator on the result of applying the sortKeyFunction.
      Since:
      6.6
    • sorted

      public final BiStream<K,V> sorted(Comparator<? super K> byKey, Comparator<? super V> byValue)
      Returns a BiStream consisting of the pairs in this stream, in the order produced by applying the byKey comparator on the keys of each pair, and then the byValue comparator on the values of pairs with equal keys.

      To sort by value then by key, consider using inverse() first.

    • count

      public final long count()
      Returns the count of pairs in this stream.
    • toMap

      public final Map<K,V> toMap()
      Returns an immutable Map that is the result of collecting the pairs in this stream. If a duplicate key is encountered, throws an IllegalStateException.

      While this is a convenient shortcut of collect(Collectors::toMap), if you have a BiStream<SubFoo, SubBar>, the return type of toMap() will be Map<SubFoo, SubBar>. To collect to Map<Foo, Bar>, use the equivalent collect(Collectors::toMap) or collect(BiCollectors.toMap()).

    • collect

      public abstract <R> R collect(BiCollector<? super K,? super V,R> collector)
      Returns an object of type R that is the result of collecting the pairs in this stream using collector.

      Please note that any Collector-returning factory method can be directly "method referenced" as BiCollector if it accepts two Function parameters corresponding to the "key" and the "value" parts respectively. For example: collect(Collectors::toConcurrentMap), collect(ImmutableSetMultimap::toImmutableSetMultimap), collect(Maps::toImmutableEnumMap), collect(ImmutableBiMap::toImmutableBiMap).

      In addition, check out BiCollectors for some other useful BiCollector implementations.

    • collect

      public final <T, R> R collect(BiCollector<? super K,? super V,T> collector, Function<? super T,R> finisher)
      Equivalent to collect(collectingAndThen(collector, finisher)) but helps to save syntactic noise.

      This is mainly used for "return" statements where you have a long BiStream chain, only the last* step needs to pass the return value of collect() to a final method cqll, for example:

      
         return new Ledger(
             BiStream.from(...)
                 .mapKeys(...)
                 .flatMapValues(...)
                 ...
                 .collect(toImmutableMap()));
       
      This syntax breaks the first-thing-first order of the BiStream pipeline by showing the last step at the top-most line. Alternatively, one can declare a local variable to hold the return value of collect(). But sometimes it's undesirable if the intermediary object's type is implementation-detail-ish or just too verbose.

      Using this method, the above example can be changed to pipeline-friendly syntax with less indentation:

      
         return BiStream.from(...)
             .mapKeys(...)
             .flatMapValues(...)
             ...
             .collect(toImmutableMap(), Ledger::new);
       
      Since:
      5.6
    • collect

      public abstract <A> A collect(A container, BiAccumulator<? super A,? super K,? super V> accumulator)
      Performs mutable reduction, as in collect(ImmutableMap.builder(), ImmutableMap.Builder::put).

      More realistically (since you'd likely use collect(toImmutableMap()) instead for ImmutableMap), you could collect pairs into two repeated proto fields:

      
         BiStream.zip(shardRequests, shardResponses)
             .filter(...)
             .collect(
                 BatchResponse.newBuilder(),
                 (builder, req, resp) -> builder.addShardRequest(req).addShardResponse(resp))
             .build();
       

      While collect(BiCollector) may perform parallel reduction if the underlying stream is parallel, this reduction is guaranteed to be sequential and single-threaded.

      Returns the populated container instance.

      Since:
      5.0
    • close

      public abstract void close()
      Closes any resources associated with this stream, typically used in a try-with-resources statement.
      Specified by:
      close in interface AutoCloseable
    • groupConsecutiveBy

      public final <G, A, R> BiStream<G,R> groupConsecutiveBy(Function<? super K,? extends G> classifier, Collector<? super V,A,? extends R> groupCollector)
      Returns a BiStream consisting of consecutive groupings from this stream. Consecutive pairs whose key maps to the same group according to classifier will have their values grouped together using groupCollector.

      For example to lazily summarize a large, pre-sorted stock price data stream per day:

      
       biStream(stockPriceData)
           .groupConsecutiveBy(PriceDatum::day, summarizingDouble(PriceDatum::price))
           .toMap();
       

      Unlike JDK groupingBy() collectors, the returned BiStream consumes the input elements lazily and only requires O(groupCollector) space for the current consecutive elements group. For instance the groupConsecutiveBy(Event::type, counting()) stream takes O(1) space. While this makes it more efficient to process large streams, the input data often need to be pre-sorted for the grouping to be useful.

      To apply grouping beyond consecutive elements, use collect(BiCollectors.groupingBy(classifier, groupCollector)) instead.

      Consecutive keys mapped to null by classifier will be grouped together.

      Parameters:
      classifier - The function to determine the group key. Because it's guaranteed to be invoked once and only once per entry, and that the returned BiStream is sequential and respects encounter order, this function is allowed to have side effects.
      Since:
      5.4
    • groupConsecutiveBy

      public final <G> BiStream<G,V> groupConsecutiveBy(Function<? super K,? extends G> classifier, BinaryOperator<V> groupReducer)
      Returns a lazy BiStream of the consecutive groups of pairs from this stream. Consecutive pairs whose key maps to the same group according to classifier will have their values reduced using the groupReducer function.

      For example to lazily find the daily opening stock price from a large, pre-sorted stock data stream:

      
       biStream(stockPriceDataSortedByTime)
           .groupConsecutiveBy(PriceDatum::day, (a, b) -> a)
           ,toMap();
       

      Unlike JDK groupingBy() collectors, the returned BiStream consumes the input elements lazily and only requires O(1) space. While this makes it more efficient to process large streams, the input data often need to be pre-sorted for the grouping to be useful.

      To apply grouping beyond consecutive elements, use collect(BiCollectors.groupingBy(classifier, groupReducer)) instead.

      Consecutive null keys are grouped together.

      Parameters:
      classifier - The function to determine the group key. Because it's guaranteed to be invoked once and only once per entry, and that the returned BiStream is sequential and respects encounter order, this function is allowed to have side effects.
      Since:
      5.4
    • groupConsecutiveBy

      public final <G, A, R> BiStream<G,R> groupConsecutiveBy(BiFunction<? super K,? super V,? extends G> classifier, BiCollector<? super K,? super V,R> groupCollector)
      Returns a BiStream consisting of consecutive groupings from this stream. Consecutive pairs mapping to the same group according to classifier will be grouped together using groupCollector.

      This can be useful when you need to apply nested groupings, for example, to first group consecutive events by year, then by continuity (happened within 24 hours):

      
       import static com.google.mu.util.stream.BiiCollectors.collectingAndThen;
      
       ImmutableListMultimap<Integer, List<Event>> continuousEventsByYear =
           biStream(events)
               .mapKeys(Event::date)
               .groupConsecutiveBy(
                   (date, event) -> date.year(),
                   collectingAndThen(
                       annual -> annual.groupConsecutiveIf(
                           (d1, d2) -> Duration.between(d1, d2).compareTo(Duration.ofHours(24)) < 0,
                           toList())))
               .collect(flatteningToImmutableListMultimap(subgroups -> subgroups));
       

      Unlike JDK groupingBy() collectors, the returned BiStream consumes the input elements lazily and only requires O(groupCollector) space for the current consecutive elements group. For instance the groupConsecutiveBy(Event::type, counting()) stream takes O(1) space. While this makes it more efficient to process large streams, the input data often need to be pre-sorted for the grouping to be useful.

      To apply grouping beyond consecutive elements, use collect(BiCollectors.groupingBy(classifier, groupCollector)) instead.

      Consecutive pairs mapped to null by classifier will be grouped together.

      Parameters:
      classifier - The function to determine the group key. Because it's guaranteed to be invoked once and only once per entry, and that the returned BiStream is sequential and respects encounter order, this function is allowed to have side effects.
      Since:
      5.5
    • groupConsecutiveIf

      public final <R> Stream<R> groupConsecutiveIf(BiStream.Partitioner<? super K,? super V> sameGroup, BiCollector<? super K,? super V,R> groupCollector)
      Returns a lazy Stream of the consecutive groups of values from this stream. Two consecutive entries belong to the same group if sameGroup.belong(key1, value1, key2, valuue2) is true. Pairs belonging to the same group are grouped together using groupCollector.

      The sameGroup predicate is always evaluated with two consecutive pairs in encounter order.

      The following example identifies price changes above a gap threshold from a stock's historical price:

      
       Map<DateTime, Double> historicalPrices = ...;
       ImmutableList<ImmutableMap<DateTime, Double>> priceClusters =
           biStream(historicalPrices)
               .groupConsecutiveIf((d1, p1, d2, p2) -> abs(p1 - p2) < gap, toImmutableMap())
               .collect(toImmutableList());
       

      Unlike JDK groupingBy() collectors, the returned Stream consumes the input elements lazily and only requires O(groupCollector) space for the current consecutive elements group. While this makes it more efficient to process large streams, the input data often need to be pre-sorted for the grouping to be useful.

      Null elements are allowed as long as the sameGroup predicate and groupCollector allow nulls.

      Since:
      5.6
    • groupConsecutiveIf

      public final <A, R> Stream<R> groupConsecutiveIf(BiPredicate<? super K,? super K> sameGroup, Collector<? super V,A,R> groupCollector)
      Returns a lazy Stream of the consecutive groups of values from this stream. Two consecutive entries belong to the same group if sameGroup.test(key1, key2) is true. Values belonging to the same group are grouped together using groupCollector.

      The sameGroup predicate is always evaluated with two consecutive keys in encounter order.

      The following example identifies price changes above a gap threshold from a stock's historical price:

      
       Stream<DoubleSummaryStatistics> priceClusters =
           biStream(stockPriceData)
               .groupConsecutiveIf((a, b) -> abs(a - b) < gap, summarizingDouble());
       

      Unlike JDK groupingBy() collectors, the returned Stream consumes the input elements lazily and only requires O(groupCollector) space for the current consecutive elements group. While this makes it more efficient to process large streams, the input data often need to be pre-sorted for the grouping to be useful.

      Null elements are allowed as long as the sameGroup predicate and groupCollector allow nulls.

      Since:
      5.4
    • groupConsecutiveIf

      public final Stream<V> groupConsecutiveIf(BiPredicate<? super K,? super K> sameGroup, BinaryOperator<V> groupReducer)
      Returns a lazy Stream of the consecutive groups of values from this stream. Two consecutive entries belong to the same group if sameGroup.test(key1, key2) is true. Values belonging to the same group are reduced using groupReducer.

      The sameGroup predicate is always evaluated with two consecutive keys in encounter order.

      Unlike JDK groupingBy() collectors, the returned Stream consumes the input elements lazily and only requires O(groupCollector) space for the current consecutive elements group. While this makes it more efficient to process large streams, the input data often need to be pre-sorted for the grouping to be useful.

      Null elements are allowed as long as the sameGroup predicate and groupCollector allow nulls.

      Since:
      5.4