Reputation: 351
String a = "hello" , b = null, c = "guru";
boolean value = Stream
.of(a, b, b.substring(2),c)
.allMatch(x -> x != null);
System.out.println(value);
This results in NPE. It seems to be doing b.substring(2)
and since b
is null
, NPE is thrown.
Why is this condition evaluated? The second expression b
is null
and hence evaluates to false
.
So, allMatch
will be false regardless of the truth values of the subsequent operations. In that case, why is it trying to evaluate b.substring(2)
?
This article and this article claim that it may not evaluate all the expressions if not necessary for determining the result. That clearly does not seem to be the case here.
Prior to Java 7 -
if(b != null && b.substring(2) != null)
this would not throw NPE because b!= null
is false
and it would return false
there itself.
So, can we say that Streams.allMatch
is not an exact equivalent of the above Java code snippet?
Upvotes: 2
Views: 946
Reputation: 36401
Streams.allMatch is not an exact equivalent of the above Java code snippet?
Of course it is not! Streams are very new way of thinking the processing of data.
Anyway your problem is (not related to this) just that for any function call, arguments are evaluated, thus the call to of
necessitate the evaluation of b.subString(2)
which obviously throw a NPE.
Related info from the Java Language Specification (emphasize is mine):
15.7.4 Argument Lists are Evaluated Left-to-Right
In a method or constructor invocation or class instance creation expression, argument expressions may appear within the parentheses, separated by commas. Each argument expression appears to be fully evaluated before any part of any argument expression to its right.
Upvotes: 1
Reputation: 198033
This has nothing to do with the allMatch
, and everything to do with the fact that all arguments to a method get evaluated before that method is called, under all circumstances. All arguments to Stream.of
, in this particular case, get evaluated before Stream.of
is called.
If you really wanted something different, the closest thing to the behavior you want would look like
Stream
.<Supplier<String>>of(() -> a, () -> b, () -> b.substring(2), () -> c)
.map(Supplier::get)
.allMatch(x -> x != null)
Upvotes: 4