Search code examples
javajava-stream

What is a way to combine multiple operations for a Stream terminal operation


I have a code that filters some elements from one list and then need to perform two operations on the filtered stream.

One way to perform this is to use a lambda that does any number of operations.

List a, b, c; // initialize and fill the lists
a.stream()
  //filtering
  .forEach(e -> {
    b.add(e);
    c.remove(e);
  });

Is there a way both operations can be performed? For example if the forEach method could take multiple arguments.

  .forEach(b::add, c::remove);

Solution

  • You could chain a series of consumers to achieve handling any length of stream with single forEach step and avoiding use of intermediate toList(). The first Consumer to forEach would need to be declared as a local variable before appling andThen(nextOperation). For example, if say, with List<String> a:

    Consumer<String> x = b::add;
    a.stream().forEach(x.andThen(c::remove));
    

    For convenience it is also possible to setup a method to chain as one consumer:

    a.stream().forEach(combine(List.of(b::add,c::remove)));
    // or
    a.stream().forEach(combine(b::add,c::remove));
    

    and implement something like this:

    public static <T> Consumer<T> combine(List<Consumer<T>> consumers) {
        return consumers.stream().reduce(Consumer::andThen).orElse(x -> {});
    }
    // or
    public static <T> Consumer<T> combine(Consumer<T> ... args) {
        return Arrays.stream(args).reduce(Consumer::andThen).orElse(x -> {});
    }