I tried to understand the GathererOp class and came over a small detail concering Gatherer.Integrator.
The two gatheres below are equivalent, both are greedy. Gatherer.Integrator.Greedy<Void, String, Integer> voidStringIntegerGreedy = (v, s, downStream) -> downStream.push(s.length()); var greedy1 = Gatherer.of(Gatherer.Integrator.ofGreedy(voidStringIntegerGreedy)); var greedy2 = Gatherer.of(Gatherer.Integrator.of(voidStringIntegerGreedy)); Inlining the lambda makes them different. var greedy = Gatherer.of(Gatherer.Integrator.ofGreedy((v, s, downStream) -> downStream.push(s.length()))); var nonGreedy = Gatherer.of(Gatherer.Integrator.of((v, s, downStream) -> downStream.push(s.length()))); If this can be a problem an introduction of an Integrator subtype like NonGreedy would have given a compiler error on the "var greedy2 =" line instead. interface Integrator { ..... static <A, T, R> NonGreedy<A, T, R> of(NonGreedy<A, T, R> integrator) { return integrator; } static <A, T, R> Greedy<A, T, R> ofGreedy(Greedy<A, T, R> greedy) { return greedy; } interface Greedy<A, T, R> extends Integrator<A, T, R> { } interface NonGreedy<A, T, R> extends Integrator<A, T, R> { } } Svein Otto Solem Retired programmer Kantega