Java Stream Filter with Lambda Expression

1. Introduction

In this quick tutorial, we’ll explore the use of the Stream.filter() method when we work with Streams in Java.

We’ll look at how to use it, and how to handle special cases with checked exceptions.

2. Using Stream.filter()

The filter() method is an intermediate operation of the Stream interface that allows us to filter elements of a stream that match a given Predicate:

Stream<T> filter(Predicate<? super T> predicate)

To see how this works, let’s create a Customer class:

public class Customer {
    private String name;
    private int points;
    //Constructor and standard getters
}

In addition, let’s create a collection of customers:

Customer john = new Customer("John P.", 15);
Customer sarah = new Customer("Sarah M.", 200);
Customer charles = new Customer("Charles B.", 150);
Customer mary = new Customer("Mary T.", 1);

List<Customer> customers = Arrays.asList(john, sarah, charles, mary);

2.1. Filtering Collections

A common use case of the filter() method is processing collections.

Let’s make a list of customers with more than 100 points. To do that, we can use a lambda expression:

List<Customer> customersWithMoreThan100Points = customers
  .stream()
  .filter(c -> c.getPoints() > 100)
  .collect(Collectors.toList());

We can also use a method reference, which is shorthand for a lambda expression:

List<Customer> customersWithMoreThan100Points = customers
  .stream()
  .filter(Customer::hasOverHundredPoints)
  .collect(Collectors.toList());

In this case, we added the hasOverHundredPoints method to our Customer class:

public boolean hasOverHundredPoints() {
    return this.points > 100;
}

In both cases, we get the same result:

assertThat(customersWithMoreThan100Points).hasSize(2);
assertThat(customersWithMoreThan100Points).contains(sarah, charles);

2.2. Filtering Collections with Multiple Criteria

Furthermore, we can use multiple conditions with filter(). For example, we can filter by points and name:

List<Customer> charlesWithMoreThan100Points = customers
  .stream()
  .filter(c -> c.getPoints() > 100 && c.getName().startsWith("Charles"))
  .collect(Collectors.toList());

assertThat(charlesWithMoreThan100Points).hasSize(1);
assertThat(charlesWithMoreThan100Points).contains(charles);

3. Handling Exceptions

Until now, we’ve been using the filter with predicates that don’t throw an exception. Indeed, the functional interfaces in Java don’t declare any checked or unchecked exceptions.

Next we’re going to show some different ways to handle exceptions in lambda expressions.

3.1. Using a Custom Wrapper

First, we’ll start by adding a profilePhotoUrl to our Customer:

private String profilePhotoUrl;

In addition, let’s add a simple hasValidProfilePhoto() method to check the availability of the profile:

public boolean hasValidProfilePhoto() throws IOException {
    URL url = new URL(this.profilePhotoUrl);
    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
    return connection.getResponseCode() == HttpURLConnection.HTTP_OK;
}

We can see that the hasValidProfilePhoto() method throws an IOException. Now if we try to filter the customers with this method:

List<Customer> customersWithValidProfilePhoto = customers
  .stream()
  .filter(Customer::hasValidProfilePhoto)
  .collect(Collectors.toList());

We’ll see the following error:

Incompatible thrown types java.io.IOException in functional expression

To handle it, one of the alternatives we can use is wrapping it with a try-catch block:

List<Customer> customersWithValidProfilePhoto = customers
  .stream()
  .filter(c -> {
      try {
          return c.hasValidProfilePhoto();
      } catch (IOException e) {
          //handle exception
      }
      return false;
  })
  .collect(Collectors.toList());

If we need to throw an exception from our predicate, we can wrap it in an unchecked exception like RuntimeException.

3.2. Using ThrowingFunction

Alternatively, we can use the ThrowingFunction library.

ThrowingFunction is an open source library that allows us to handle checked exceptions in Java functional interfaces.

Let’s start by adding the throwing-function dependency to our pom:

<dependency>
    <groupId>pl.touk</groupId>
    <artifactId>throwing-function</artifactId>
    <version>1.3</version>
</dependency>

To handle exceptions in predicates, this library offers us the ThrowingPredicate class, which has the unchecked() method to wrap checked exceptions.

Let’s see it in action:

List customersWithValidProfilePhoto = customers
  .stream()
  .filter(ThrowingPredicate.unchecked(Customer::hasValidProfilePhoto))
  .collect(Collectors.toList());

4. Conclusion

In this article, we saw an example of how to use the filter() method to process streams. We also explored some alternatives to handle exceptions.

As always, the complete code is available over on GitHub.

Related posts:

LinkedList trong java
Spring Boot Actuator
Giới thiệu SOAP UI và thực hiện test Web Service
Java Program to Generate All Subsets of a Given Set in the Lexico Graphic Order
Spring Boot - CORS Support
Convert Hex to ASCII in Java
Spring RestTemplate Error Handling
Java Program to Implement the Alexander Bogomolny’s UnOrdered Permutation Algorithm for Elements Fro...
String Processing with Apache Commons Lang 3
A Guide to ConcurrentMap
Inject Parameters into JUnit Jupiter Unit Tests
Java Program to Perform Inorder Non-Recursive Traversal of a Given Binary Tree
Logout in an OAuth Secured Application
Spring Boot - Google OAuth2 Sign-In
Map Interface trong java
Spring Cloud – Bootstrapping
Hướng dẫn Java Design Pattern – MVC
Java Program to implement Array Deque
Removing all duplicates from a List in Java
Java Program to Find Minimum Number of Edges to Cut to make the Graph Disconnected
String Initialization in Java
Java Program to Perform Searching Using Self-Organizing Lists
Mệnh đề if-else trong java
Hướng dẫn sử dụng lớp Console trong java
Integer Constant Pool trong Java
The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5
Redirect to Different Pages after Login with Spring Security
Java Program to Implement ConcurrentLinkedQueue API
Java Program to Find Nearest Neighbor for Static Data Set
The DAO with JPA and Spring
Java Program to Check if any Graph is Possible to be Constructed for a Given Degree Sequence
Convert String to Byte Array and Reverse in Java