Why is this an issue?

Stateless stream gatherers, which process each element of the stream independently, don’t need an initializer function. That’s because the role of the initializer function is to set up the gatherer’s private state object.

The gatherer interface provides factory methods that create gatherers without taking an initializer as an argument:

Using these specific factory methods to create stateless gatherers is preferable because it clearly communicates their stateless nature.

This rule reports the use of ofSequential(Gatherer.Integrator<Void,T,R> integrator, BiConsumer<Void, Gatherer.Downstream<? super R>> finisher) when it returns a stateless gatherer.

Code examples

Noncompliant code example

private static Gatherer inRange(int start, int end) {
    return Gatherer.<Integer, Void, Integer>ofSequential(
      () -> null, // Noncompliant: unnecessary initializer
      (_, element, downstream) -> {
        if (element >= start && element <= end)
          return downstream.push(element - start);
        return !downstream.isRejecting();
      },
      (_, downstream) -> downstream.push(-1)
    );
}

Compliant solution

private static Gatherer inRange(int start, int end) {
    return Gatherer.<Integer, Integer>ofSequential(
      (_, element, downstream) -> {
        if (element >= start && element <= end)
          return downstream.push(element - start);
        return !downstream.isRejecting();
      },
      (_, downstream) -> downstream.push(-1)
    );
}