I have a stream and would like to check if all match a filter. If all match, return true
.
But, if the stream is empty, I'd like to return false
.
How can I do this?
Example code:
public boolean validate(Stream<Whatever> stream) {
// Problem: returns **true** if stream empty.
// How can **false** be returned if stream is empty?
return stream.allMatch(Whatever::someCheck);
}
You could use
public boolean validate(Stream<Whatever> stream) {
return stream.map(Whatever::someCheck).reduce(Boolean::logicalAnd).orElse(false);
}
which expresses the intent. We map each element to a boolean
value expressing whether it matches and reducing all of them with a logical and operation which will yield true
iff all of them were true
. reduce
will return an empty Optional
if there were no elements, which we map to false
using orElse(false)
, as intended.
The only disadvantage is that this is non short-circuiting, i.e. does not stop immediately at the first non-matching element.
A solution still supporting short-circuiting might be a bit more evolved:
public boolean validate(Stream<Whatever> stream) {
boolean parallel = stream.isParallel();
Spliterator<Whatever> sp = stream.spliterator();
if(sp.getExactSizeIfKnown() == 0) return false;
Stream.Builder<Whatever> b = Stream.builder();
if(!sp.tryAdvance(b)) return false;
return Stream.concat(b.build(), StreamSupport.stream(sp, parallel))
.allMatch(Whatever::someCheck);
}
This is a variant of Eugene’s answer, but it doesn’t loose characteristics or parallelism and might be a bit more efficient in general.