Search code examples
javajava-streampeek

Java: How to count and process elements in a Stream without auxiliary structures or peek()?


I'm working with Java streams and I need a method to both count all elements in the stream and, at the same time, perform operations on a subset of them using skip() and limit(). I'm aiming to do this without using any auxiliary structures to reduce heap space usage, because the data entered can be very large.

I'd also prefer to steer clear of the peek() method due to its potential side effects in specific scenarios, as detailed in this 4Comprehension article.

public static <T> long extractAndProcess(Stream<T> streamData, int pageIndex, int itemsPerPage,   Consumer<T> itemHandler) {

    long startPosition = (long) pageIndex * itemsPerPage;
    AtomicLong totalCount = new AtomicLong();

    streamData.peek(item -> totalCount.incrementAndGet())
              .skip(startPosition)
              .limit(itemsPerPage)
              .forEachOrdered(itemHandler);

    return totalCount.get();
}

I tried to use peek() here, but in combination with .limit() it doesn't work as I assumed in the specific cases.


Solution

  • The only viable solution that deals with the case you've described looks like

    streamData.forEachOrdered(elem -> {
      int i = totalCount.getAndIncrement();
      if (i >= startPosition && i < startPosition + itemsPerPage) {
        itemHandler.accept(i);
      }
    })
    

    I don't believe a better solution exists; streams are really not designed to do what you're trying to do with them.