Java Predicate Example – Predicate Filter

In mathematics, a predicate is commonly understood to be a boolean-valued function 'P: X? {true, false}', called the predicate on X. Informally, a strong. It can be thought of as an operator or function that returns a value that is either true or false.

Java 8 Predicates Usage

In Java 8, Predicate is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. So, where you think, we can use these true/false returning functions in day to day programming? I will say you can use predicates anywhere where you need to evaluate a condition on group/collection of similar objects such that evaluation can result either in true or false.

For example, you can use predicates in these realtime usecases

  1. Find all children born after a particular date
  2. Pizzas ordered a specific time
  3. Employees greater than certain age and so on..

Java Predicate Class

So java predicates seems to be interesting thing. Let’s go deeper.

As I said, Predicate is functional interface. It mean we can pass lambda expressions wherever predicate is expected. For example one such method is filter() method from Stream interface.

/**
 * Returns a stream consisting of the elements of this stream that match
 * the given predicate.
 *
 * <p>This is an <a href="package-summary.html#StreamOps">intermediate
 * operation</a>.
 *
 * @param predicate a non-interfering stateless predicate to apply to each element to determine if it
 * should be included in the new returned stream.
 * @return the new stream
 */
Stream<T> filter(Predicate<? super T> predicate);

We can assume a stream as a mechanism to create a sequence of elements supporting sequential and parallel aggregate operations. It means we can anytime collect and perform some operation of all elements present in the stream in one call.

So, essentially we can use stream and predicate to –

  • first filter certain elements from a group, and
  • then perform some operation on filtered elements.

Using Predicate on a collection

To demonstrate, we have an Employee class as below:

package predicateExample;

public class Employee {
   
   public Employee(Integer id, Integer age, String gender, String fName, String lName){
       this.id = id;
       this.age = age;
       this.gender = gender;
       this.firstName = fName;
       this.lastName = lName;
   } 
    
   private Integer id;
   private Integer age;
   private String gender;
   private String firstName;
   private String lastName;

   //Please generate Getter and Setters

   //To change body of generated methods, choose Tools | Templates.
    @Override
    public String toString() {
        return this.id.toString()+" - "+this.age.toString(); 
    }
}

1. All Employees who are male and age more than 21

public static Predicate<Employee> isAdultMale() 
{
    return p -> p.getAge() > 21 && p.getGender().equalsIgnoreCase("M");
}

2. All Employees who are female and age more than 18

public static Predicate<Employee> isAdultFemale() 
{
    return p -> p.getAge() > 18 && p.getGender().equalsIgnoreCase("F");
}

3. All Employees whose age is more than a given age

public static Predicate<Employee> isAgeMoreThan(Integer age) 
{
    return p -> p.getAge() > age;
}

You can build more of them as an when needed. So far so good. Far using above methods I have included above 3 methods in EmployeePredicates.java :

package predicateExample;

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class EmployeePredicates 
{
    public static Predicate<Employee> isAdultMale() {
        return p -> p.getAge() > 21 && p.getGender().equalsIgnoreCase("M");
    }
    
    public static Predicate<Employee> isAdultFemale() {
        return p -> p.getAge() > 18 && p.getGender().equalsIgnoreCase("F");
    }
    
    public static Predicate<Employee> isAgeMoreThan(Integer age) {
        return p -> p.getAge() > age;
    }
    
    public static List<Employee> filterEmployees (List<Employee> employees, 
                                                Predicate<Employee> predicate) 
    {
        return employees.stream()
        			.filter( predicate )
        			.collect(Collectors.<Employee>toList());
    }
}   

You see I have created another utility method filterEmployees() to show java predicate filter. It is basically to make code clean and less repetitive. You can also write more than one predicates to make predicate chain, as we do in builder pattern.

So, in this function we pass the list of employees and we pass a predicate, then this function will return a new collection of employees satisfying the condition mentioned in parameter predicate.

package predicateExample;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static predicateExample.EmployeePredicates.*;

public class TestEmployeePredicates 
{
    public static void main(String[] args)
    {
        Employee e1 = new Employee(1,23,"M","Rick","Beethovan");
        Employee e2 = new Employee(2,13,"F","Martina","Hengis");
        Employee e3 = new Employee(3,43,"M","Ricky","Martin");
        Employee e4 = new Employee(4,26,"M","Jon","Lowman");
        Employee e5 = new Employee(5,19,"F","Cristine","Maria");
        Employee e6 = new Employee(6,15,"M","David","Feezor");
        Employee e7 = new Employee(7,68,"F","Melissa","Roy");
        Employee e8 = new Employee(8,79,"M","Alex","Gussin");
        Employee e9 = new Employee(9,15,"F","Neetu","Singh");
        Employee e10 = new Employee(10,45,"M","Naveen","Jain");
        
        List<Employee> employees = new ArrayList<Employee>();
        employees.addAll(Arrays.asList(new Employee[]{e1,e2,e3,e4,e5,e6,e7,e8,e9,e10}));
               
        System.out.println(	filterEmployees(employees, isAdultMale()) );
        
        System.out.println( filterEmployees(employees, isAdultFemale()) );
        
        System.out.println( filterEmployees(employees, isAgeMoreThan(35)) );
        
		//Employees other than above collection of "isAgeMoreThan(35)" 
		//can be get using negate()
        System.out.println(filterEmployees(employees, isAgeMoreThan(35).negate()));
    }
}

Output:

[1 - 23, 3 - 43, 4 - 26, 8 - 79, 10 - 45]
[5 - 19, 7 - 68]
[3 - 43, 7 - 68, 8 - 79, 10 - 45]
[1 - 23, 2 - 13, 4 - 26, 5 - 19, 6 - 15, 9 - 15]

Predicates are really very good addition in Java 8 and I am going to use it whenever I will get chance.

Final Thoughts on Predicates in Java 8

  1. They move your conditions (sometimes business logic) to a central place. This helps in unit-testing them separately.
  2. Any change need not be duplicated into multiple places. Java predicate improves code maintenance.
  3. The code e.g. “filterEmployees(employees, isAdultFemale())” is very much readable than writing a if-else block.

Well, those are my thoughts in Java 8 predicates. What do you think of this feature? Share with all of us in the comments section.

Happy Learning !!

Read More :

Java Predicate Negate Example
Java chained predicates – logical AND and logical OR operations

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

22 thoughts on “Java Predicate Example – Predicate Filter”

  1. under TestEmployeePredicates shouldnt it be “EmployeesPredicates.filterEmployees()” and “EmployeesPredicates.isAdultFemale()” (e.g.)?

  2. Using predicates will have performance impact on large collection of Objects right… ???

    I have tried filtering out the even numbers from the a list containing 0-1500 using Guava Predicates and normal conventional way of for and if loop implementation .

    I guess it will apply to the Java Se8 Predicate case as well right?

    • I also tried to find the difference in performance. You are right it’s much bigger than alternate ways of for loop iterations. Below is code I tried and executed it multiple times with almost same result.

      public static void main(String[] args){
      List list = new ArrayList();
      for(int i = 1; i< 100000; i++){ list.add(i); } long startTime = System.currentTimeMillis(); Stream
      stream = list.stream();
      Integer[] evenNumbersArr = stream.filter(i -> i%2 == 0).toArray(Integer[]::new);
      System.out.println(evenNumbersArr);

      long endTime = System.currentTimeMillis();
      System.out.println(endTime - startTime);

      startTime = System.currentTimeMillis();
      Integer[] evenNumbersArr2 = new Integer[list.size()];
      for(Integer i : list){
      if(i%2 == 0) evenNumbersArr2[i] = i;
      }
      System.out.println(evenNumbersArr2);

      endTime = System.currentTimeMillis();
      System.out.println(endTime - startTime);
      }

      Output:

      [Ljava.lang.Integer;@d46ca6
      57
      [Ljava.lang.Integer;@117d9a3
      3

      • This means using streams, slows down the performance atleast in this case. I tried this too, and with traditional approach results are faster.

        • With a trivial example like this then yes the overhead of stream processing is probably not worth it. I think that one of the central tenets of streams is that you can chain operations together and they are ‘squashed’ and only evaluated once on the terminal operation, whereas pre-Java8 you would have to loop over the collection each time for each operation. The stream API also gives you the powerful option to parallelise the processing simply by calling .parallel() on an existing stream.

          • Streams are useful when they are used parallel for large collections otherwise its an overhead to create streams.
            I also had evaluated the performance for loops and parallel streams win in this case.
            For small collections traditional or Java 5 way is useful.

          • Agree. There is a trade off between clean code and performance gain. For small collections , the performance gain is not that much but the code readability increase many fold. I will go for clean code in this case considering powerful hardware available these days.

  3. Hi,

    In TestEmployeePredicates class,you called filterEmployee() method.where it is there and can you write a Predicate interface.

    • Filter method is defined in “EmployeePredicates”. It’s last method.
      Yes, you can make predicate interface. Make all methods inside it, default methods.

Comments are closed.

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.