Why is this an issue?

There are two types of stream operations: intermediate operations, which return another stream, and terminal operations, which return something other than a stream. Intermediate operations are lazy, meaning they aren’t actually executed until and unless a terminal stream operation is performed on their results. Consequently, if the result of an intermediate stream operation is not fed to a terminal operation, it serves no purpose, which is almost certainly an error.

This rule raises an issue when the result of an intermediate stream operation is not consumed by a terminal operation on all execution paths. Exception-handling paths are exempt.

Noncompliant code example

widgets.stream().filter(b -> b.getColor() == RED); // Noncompliant
Stream<Widget> pipeline = widgets.stream().filter(b -> b.getColor() == RED); // Noncompliant; not consumed when widgets is empty
if (!widgets.isEmpty()) {
  logger.info("Processing widgets");
  pipeline.forEach(w -> logger.info("Widget: {}", w));
}

Compliant solution

int sum = widgets.stream()
                      .filter(b -> b.getColor() == RED)
                      .mapToInt(b -> b.getWeight())
                      .sum();
Stream<Widget> pipeline = widgets.stream()
                                 .filter(b -> b.getColor() == GREEN)
                                 .mapToInt(b -> b.getWeight());
sum = pipeline.sum();

Reorder the code so that the stream is consumed on all paths:

if (!widgets.isEmpty()) {
  logger.info("Processing widgets");
  Stream<Widget> pipeline = widgets.stream().filter(b -> b.getColor() == RED); // Compliant; always consumed
  pipeline.forEach(w -> logger.info("Widget: {}", w));
}

Resources