The Predicate interface
A Predicate represents a filter or condition. It takes an object as its
input perameter and returns true or false depending on whether the object in question
matches the condition or filter in question. The Java Predicate interface is one of the
standard functional interfaces prodivded out of the box
so that you can define lambda expressions that define a condition or filter.
To write a predicate as a lambda expression in Java, we generally write the object argument followed by the
expression that returns true/false. For example, a predicate that filters strings on whether they are
10+ characters in length would look like this:
(str) -> str.length() >= 10
Predicates with the Stream.filter() method: how to filter a list or stream using a lambda expression
The most common use of a Predicate is with the Stream.filter() method. We can stream
a list (or other collection) of objects and then filter them on a particular condition before collecting the results.
For example, we can iterate through all strings in a list that are 10 or more characters in length as follows:
List<String> strings = ...
strings.stream()
.filter((str) -> str.length() >= 10)
So to get a sublist of all of the "long" strings, we could write:
List<String> strings = ...
List<String> longStrings = strings.stream()
.filter((str) -> str.length() >= 10)
.collect(Collectors.toList());
Defining a method that takes a lambda expression as a filter or condition
As with any other of the standard Java functional interfaces, we are not
forced to use Predicate only with the Stream class. The Predicate interface
is equally useful when we want to write our own methods that will take a lambda expression as a filter or condition.
The Predicate interface provides a test() method. This will invoke the lambda expression that defines
the filter or condition. For example, we could write a findCachedObjects() method which takes a lambda expression defining the
specific objects we wish to retrieve from our cache:
public List<T> findCachedObjects(Predicate<T> whichObjects) {
List<T> ret = new ArrayList();
for (T obj : allCachedObjects()) {
if (whichObjects.test(obj)) {
ret.add(obj);
}
}
return ret;
}
Then, the findCachedObjects() method can be invoked as follows:
List<Customer> matchingCustomers =
findCachedObjects(c -> c.getCustomerName().equals(searchName));
The pros and cons of stream.filter() with a lambda expression
As illustrated above, the filter() method makes it extremely simple to pass in a lambda exprssion
as a Predicate (filter) to get a sublist of matching items. This alluring simplicity can also be
its downfall in the hands of a lazy developer!
If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.
Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.