Search code examples
javajava-stream

Java Stream limit vs Standard for loop performance


In a case I need n elements from a collection with a certain filter. In a standard for loop, I can break if a reached n elements without going throufh the rest of elements

Collection limitConcition = new ... // Instantiates the collection
for(Item item: myCollection) {
  if (item.verifyCondition()) {
    // do some magic
    limitCondition.add(item);
    if (size > limit) break;
  }
}

But in Java stream I need to do something like:

myCollection.stream()
.map(item -> doSomeMagic())
.filter(//someCondition)
.limit(n)

In the second approach I need to go through all the items of the collection and then limit, while in the first approach once I reached my limit I can break without going through the rest of elements. I see a performance issue and memory waste. Is there a way to use Stream in this case in a performant way ?

I did try both methods, And I am trying to find out if there is a Stream that match my performance criteria.


Solution

  • Think of stream pipeline operations as a chain of people passing buckets to one another to put out a fire.

    Each person is asked for another bucket, then turns to the person behind it and asks for a bucket, and so on until the source of the water (the source of the stream).

    So you don't go through the entire collection in the second approach. Each operation in a stream is responsible for asking the operation before it for another item.

    So when the limit(n) part of the chain reaches the limit, it no longer asks for elements from the parts that precede it. Instead, if an operation in front of it turns to it and asks for the next "bucket", it tells it "I don't have any more".

    This means that to the collector or whatever follows the limit(n) operation, after n elements, it will get an "end of stream" and will finish its operations accordingly.