We will start with What Predicate is and then write example on how to filter data with predicates and also discuss about predicate chaining.
Previous posts
java.util.function Predicate?Predicate is like a condition checker, which accepts one argument of type T and return the boolean value.
It's a functional interface with functional method test(T). Here, Object is typed.
@FunctionalInterface
interface Predicate<T> {
public boolean test(T t);
}
Consider we have Collection of employees and we want to filter them based on age, sex, salary and/ or with any other combinations. We can do that with Predicate.
Let's understand it with a short example.
class Employee {
private long id;
private String firstName;
private String lastName;
private int age;
private Sex sex;
private int salary;
// getters, constructor, hashCode, equals, to String
}
Defining predicates for filtering
Predicate<Employee> male = e -> e.getSex() == Sex.MALE;
Predicate<Employee> female = e -> e.getSex() == Sex.FEMALE;
Predicate<Employee> ageLessThan30 = e -> e.getAge() < 30;
Predicate<Employee> salaryLessThan20 = e -> e.getSalary() < 20000;
Predicate<Employee> salaryGreaterThan25 = e -> e.getSalary() > 25000;
Filtering employees with Predicates
employees.stream().filter(male).collect(Collectors.toList());
employees.stream().filter(female).collect(Collectors.toList());
employees.stream().filter(ageLessThan30).collect(Collectors.toList());
employees.stream().filter(salaryLessThan20).collect(Collectors.toList());
Here, employees reference is of type java.util.List.
Collections framework is retrofitted for Streaming API and have stream() and parallelStream() methods along with few other additions like filter() method is defined in Stream. We are streaming employees collection and filtering them based on the Predicate and then collecting as java.util.List.
java.util.function.Predicate have three default method. Two of them and(Predicate<T> other) and or(Predicate<T> other) is used for predicate chaining.
Let's say, we want to filter collection of employees which involves multiple conditions like
Let's understand it with an example code.
// Point 1
Predicate<Employee> male = e -> e.getSex() == Sex.MALE;
// Point 2
Predicate<Employee> female = e -> e.getSex() == Sex.FEMALE;
// Point 3
Predicate<Employee> ageLessThan30 = e -> e.getAge() < 30;
// Point 4
Predicate<Employee> salaryLessThan20 = e -> e.getSalary() < 20000;
// Point 5
Predicate<Employee> salaryGreaterThan25 = e -> e.getSalary() > 25000;
// Point 6
Predicate<Employee> salaryLessThan20OrGreateThan25 = salaryLessThan20.or(salaryGreaterThan25);
// Point 7
Predicate<Employee> allMaleSalaryLessThan20 = male.and(salaryLessThan20);
// Point 8
Predicate<Employee> allMaleAgeLessThan30 = male.and(ageLessThan30);
// Point 9
Predicate<Employee> allFemaleSalaryGreaterThan25 = female.and(salaryGreaterThan25);
// Point 10
Predicate<Employee> allMaleSalaryLessThan20OrGreateThan25 = male.and(salaryLessThan20OrGreateThan25);
employees.stream().filter(allMaleSalaryLessThan20).collect(Collectors.toList());
employees.stream().filter(allMaleAgeLessThan30).collect(Collectors.toList());
employees.stream().filter(allFemaleSalaryGreaterThan25).collect(Collectors.toList());
employees.stream().filter(allMaleSalaryLessThan20OrGreateThan25).collect(Collectors.toList());
This is how we can use Predicate to filter in-memory data. I hope you find this post informative and helpful. You can get the full example code on Github.