Java 8 Streams API is very robust and feature-rich API. It provides multiple ways to write beautiful and fewer lines of code. In that series, there is an interface Predicate Interface. Let’s start understanding Java Predicate Interface.

1. What is Java 8 Predicate and Understanding Java Predicate Interface.

Java 8 Predicate Interface is a functional interface, By functional interface you know it will have only one abstract method and the programmer writes the body for that one abstract method as part of Lambda expression. Predicate is a type of functional interface which takes a parameter and return a boolean result. Let’s look at the Predicate Interface.

package java.util.function;
@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);

    ...
}

Here as you can see it has an abstract method “test” which accepts a parameter and returns a boolean value either true or false. Let’s see some example.

//Use with Stream API
List<Employee> empList = getEmployeeList() // lets say some function which return list of employee, Employee object has age and name variables. 
Predicate<Employee> p1 = p -> p.getAge() > 21;

List<Employee> newEmpList = empList.stream()
  .filter(p1)
  .collect(Collectors.<Employee>toList()); // List will iterate and check for all the employee having age greater than 21

The above filter example takes Predicate and filters the values based on predicates result. If the result is true it keeps the employee and if the result is false it discards the employee. In the end, the collect method collects it and form another list. Predicate is used with the Optional class as well.

2. Chaining Predicate interfaces.

Here are the other important methods from Predicate interface.

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) &amp;&amp; other.test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
    ...
}

Predicate interface contains three more methods for logical chaining of multiple Predicates.

2.1 Chain Predicate using ‘And’ condition.

This example shows how two predicates are joined using and condition.

//Use with Stream API
List<Employee> empList = getEmployeeList();
Predicate<Employee> p1 = p -> p.getAge() > 21;
Predicate<Employee> p2 = p -> p.getAge() < 50;

Predicate<Employee> p3 = p1.and(p2);

List<Employee> newEmpList = empList.stream()
  .filter(p3)
  .collect(Collectors.<Employee>toList()); // List will iterate and check for all the employee having age greater than 21 and less than 50

2.2 Chain Predicate using ‘Or’ condition.

This example shows how two predicates are joined using ‘or’ condition.

//Use with Stream API
List<Employee> empList = getEmployeeList();
Predicate<Employee> p1 = p -> p.getAge() < 21;
Predicate<Employee> p2 = p -> p.getAge() > 50;

Predicate<Employee> p3 = p1.or(p2);

List<Employee> newEmpList = empList.stream()
  .filter(p3)
  .collect(Collectors.<Employee>toList()); // List will iterate and check for all the employee having age less than 21 or greater than 50

2.3 Negate Predicate.

This example shows how to negate predicates. Turn true to false and vice versa.

//Use with Stream API
List<Employee> empList = getEmployeeList();
Predicate<Employee> p1 = p -> p.getAge() > 21;

Predicate<Employee> p2 = p1.negate(p1);

List<Employee> newEmpList = empList.stream()
  .filter(p2)
  .collect(Collectors.<Employee>toList()); // List will iterate and check for all the employee having age less than 21 or equal to 21

3. Conclusion

In this blog, we discussed how to use Java 8 Predicate interface and it’s important method. Later we discussed on chaining of the Predicate interface. That’s it on Understanding Java Predicate Interface. You can further read about Functional Interfaces.