In this post, we will cover following items.
- What is java.util.function.Predicate?
- How to filter data with Predicates?
- Predicate chaining.
Java 8 introduced many new features like Streaming API, Lambdas, Functional interfaces, default methods in interfaces and many more.
Today, we will discuss about Predicate
interface added in java.util.function package and its usage in filtering in-memory data.
What is 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(Object)
. Here, Object is typed.
@FunctionalInterface
interface Predicate<T> {
public boolean test(T t);
}
How we can filter data with Predicates?
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 this with one 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.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.
Predicate chaining
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.
Filtering employees with multiple predicates
Let's say, we want to filter collection of employees which involves multiple conditions like
- all male salary less than 20k.
- all female salary greater than 25k.
- all male salary either less than 20 k or greater than 25k.
Let's understand this with quick example.
Defining predicates
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;
Predicate<Employee> salaryLessThan20OrGreateThan25 = salaryLessThan20.or(salaryGreaterThan25);
Predicate<Employee> allMaleSalaryLessThan20 = male.and(salaryLessThan20);
Predicate<Employee> allMaleAgeLessThan30 = male.and(ageLessThan30);
Predicate<Employee> allFemaleSalaryGreaterThan25 = female.and(salaryGreaterThan25);
Predicate<Employee> allMaleSalaryLessThan20OrGreateThan25 = male.and(salaryLessThan20OrGreateThan25);
Line 1 => Predicate test for employee male
Line 2 => Predicate test for employee female
Line 3 => Predicate test for employee age less than 30
Line 4 => Pedicate test for employee salary less than 20000
Line 8 => Predicate test for employee male and salary less than 20000
Line 10 => Predicate test for employee female and salary greater than 25000
Line 12 => Predicate test for employee male and salary either less than 20000 or greater than 25000
Filtering employees with predicate chaining
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.