Eran
Eran

Reputation: 393801

Can IntStream::noneMatch not evaluate the predicate on all the elements of the stream?

I read the Javadoc of IntStream::noneMatch

It says : 

Returns whether no elements of this stream match the provided predicate. May not evaluate the predicate on all elements if not necessary for determining the result. If the stream is empty then true is returned and the predicate is not evaluated. 

I was wondering if there's an actual scenario in which noneMatch will not evaluate the predicate on all the elements of the stream and return true (in the case where noneMatch returns false, it is clear that the predicate is only evaluated on elements until the first match is found).

The only scenario I could think of was that if the stream pipeline would have a filter whose predicate is the exact negative of the predicate of noneMatch, perhaps noneMatch would return true without testing any elements.

However, when tested with the following code :

boolean out = IntStream.range(1, 10000)
                  .filter(i -> i % 2 == 0)
                  .peek(System.out::println)
                  .noneMatch(i -> i % 2 == 1);
System.out.println(out);

I get an output of even numbers starting from 2 to 9998:

2
4
6
...
9998
true

which means the entire stream was evaluated, even though the filter returns only even integers, while the predicate of noneMatch requires no odd integers to be found, so it should be able to return true without evaluating any elements.

So, when the Javadoc says May not evaluate on all elements., does it only refer to the cases in which noneMatch returns false?

EDIT:

I just wanted to clarify that my question is not why the code I posted evaluates the entire stream. My question is whether there's a scenario in which noneMatch returns true without evaluating the entire stream.

Upvotes: 2

Views: 2972

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500385

so it should be able to return true without evaluating any elements

No, in order to check that none of the elements match, it has to check everything. In other words, if it returns true then it will definitely have looked at everything. To put it another way - your logic relied on what the predicate does, so how can it return without evaluating any elements, when that means the predicate would never be applied?

The only way it could return true without evaluating all elements would be if it could tell just by the type of the stream and something about the predicate. For example, if the stream "knew" that it was a stream of UUID references, and the predicate was "match strings" then it wouldn't need to evaluate things - but I doubt that there's anything that tries for that sort of optimization.

If (and only if) it finds something which does match the predicate, however, it can return false without looking at the rest of the items.

For example, if you change your code to:

boolean out = IntStream.range(1,10000)
               .peek(System.out::println)
               .noneMatch(i->i%4==3);
System.out.println(out);

then you'll get output of:

1
2
3
false

Upvotes: 4

Related Questions