Is it possible to check if an array (or collection) contains element 5 and element other than 5. In one stream returning boolean result instead of using two streams:
int[] ints = new int[]{1, 2, 3, 4, 5};
boolean hasFive = IntStream.of(ints).anyMatch(num -> num == 5);
boolean hasNonFive = IntStream.of(ints).anyMatch(num -> num != 5);
boolean result = hasFive && hasNonFive;
Here's two solutions involving my StreamEx library. The core feature I'm using here is the concept of short-circuiting collectors. My library enhances the Collector
concept to provide the ability to short-circuit (which works both for sequential and parallel streams)
If predicates are like in your sample (one is the opposite of another), you may use partitioningBy
:
Map<Boolean, Optional<Integer>> map = IntStreamEx.of(ints).boxed()
.partitioningBy(num -> num == 5, MoreCollectors.first());
Now you should check whether both mappings are present:
System.out.println(map.values().stream().allMatch(Optional::isPresent));
Or in single statement:
System.out.println(IntStreamEx.of(ints).boxed()
.partitioningBy(num -> num == 5, MoreCollectors.first())
.values().stream().allMatch(Optional::isPresent));
Here we're using MoreCollectors.first()
short-circuiting collector. This solution is similar to one proposed by @user140547, but it will actually stop processing as soon as both elements are found.
For two custom predicates it's possible to use pairing
collector which combines the results of two collectors (preserving the short-circuiting if input collectors are short-circuiting). But first, we need anyMatching
collector (which is absent in my library):
import static one.util.streamex.MoreCollectors.*;
static <T> Collector<T, ?, Boolean> anyMatching(Predicate<T> pred) {
return collectingAndThen(filtering(pred, first()), Optional::isPresent);
}
Collector<Integer, ?, Boolean> hasFive = anyMatching(num -> num == 5);
Collector<Integer, ?, Boolean> hasNonFive = anyMatching(num -> num != 5);
Collector<Integer, ?, Boolean> hasBoth = pairing(hasFive, hasNonFive,
(res1, res2) -> res1 && res2);
System.out.println(IntStreamEx.of(ints).boxed().collect(hasBoth));
In this specific case, i.e. you want to know whether a stream or array contains both, a matching and a nonmatching element (an element matching the predicate’s negation), you can do it much simpler.
First, test whether the first element matches the predicate or its negation, then, search whether the stream contains any match of the opposite:
IntPredicate predicate=i -> i==5;
if(ints.length>0 && predicate.test(ints[0]))
predicate=predicate.negate();
boolean result = IntStream.of(ints).anyMatch(predicate);
That’s it. In case you don’t have an array or collection as the stream source, but an arbitrary stream, testing the first element is a bit trickier:
IntPredicate[] tmp={ null };
Spliterator.OfInt sp=intStream.spliterator();
boolean result = sp.tryAdvance(
(int i) -> tmp[0]=predicate.test(i)? predicate.negate(): predicate)
&& StreamSupport.intStream(sp, false).anyMatch(tmp[0]);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With