Best way to share/re-use a common sequence of operations between Java streams

Viewed 97

If I have a common sequence of operations in two streams, how can have them be shared to avoid duplicating the code? So far I have found that I can use:

Stream<U> commonSequence(Stream<T> upstream) {
    return upstream.op1().op2().op3()
}

And then use it as

commonSequence(upStream()).downStream()

But then things are not really written in the order in which they happen. Am I overlooking some trick that would allow me to write something like:

upStream().wrap(commonPart).downStream()
1 Answers

You can make your own Collector, but it will likely not be as efficient.

The following collector is somewhat equivalent to doing filter("foo").limit(10).

class FilterFooAndLimit10Collector<T> implements Collector<T, List<T>, Stream<T>> {
  @Override
  public Supplier<List<T>> supplier() {
    return () -> new ArrayList<>();
  }
  
  @Override
  public BiConsumer<List<T>, T> accumulator() {
    return (list, elem) -> {
      if (!"foo".equals(elem)) list.add(elem);
    };
  }
  
  @Override
  public BinaryOperator<List<T>> combiner() {
    return (list1, list2) -> {
      var res = new ArrayList<T>(list1.size() + list2.size());
      res.addAll(list1);
      res.addAll(list2);
      return res;
    };
  }
  
  @Override
  public Function<List<T>, Stream<T>> finisher() {
    return list -> list.stream().limit(10);
  }
  
  @Override
  public Set<Collector.Characteristics> characteristics() {
    return new HashSet<>();
  }
}

You can use it like this:

Stream
  .of("foo", "bar", "baz", "foo", "quux", "corge", "fred", "waldo", "spam", "ham", "eggs", "foo", "foobar", "xyzzy")
  .collect(new FilterFooAndLimit10Collector<String>())
  .forEach(x -> System.out.println(x));

This will yield the output

bar
baz
quux
corge
fred
waldo
spam
ham
eggs
foobar

You can, of course, modify it to take constructor parameters for a wider range of behavior, or optimize it using some other data structure, but I would personally just prefer commonSequence(stream).

Related