'Is it possible to use a Predicate in a Java Stream when a specific condition is met?

Let's say that I have a method with two predicates: (simplified for clarity)

public List<Data> getData(List<OtherData> otherData, String value, String otherValue) {

    Predicate<OtherData> predicate1 = otherData -> otherData.getValue().equals(value))
    Predicate<OtherData> predicate2 = otherData -> otherData.getOtherValue().equals(otherValue))

    return otherData.stream()
        .filter(predicate1.and(predicate2))
        .map(otherData -> Data.of(otherData))
        .collect(Collectors.toList())
}

But let's say that I'd like to change this code so the predicates are created and used dynamically basing on the availibility of String value and String otherValue - whenever they are not null.

I have seen such approach using javax.persistence.criteria.CriteriaBuilder and javax.persistence.criteria.CriteriaQuery, creating a List<Predicate> and filling this list using some ifology like

List predicates; if(value != null) { predicates.add(//predicate logic here); }

and using them later in CriteriaQuery.query.where()

but this is persistence related stuff, and I would like to do it in a non-persistent context (and without the ifology if possible)

Is this possible?



Solution 1:[1]

You can implement the predicates in the following way: value == null || elementValue.equals(value).

Predicate<OtherData> valueNull = v -> Objects.isNull(value);
Predicate<OtherData> predicate1 = valueNull.or(otherData -> otherData.getValue().equals(value)))

Solution 2:[2]

You can do something similar by using Stream.reduce. In a generic way:

List<Predicate<T>> predicates = ...
Predicate<T> combined = predicates.stream()
        .reduce(t -> true, Predicate::and);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Adam Siemion
Solution 2 Rob Spoor