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.