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:

Merging Two Maps with Java 8
Java Program to Implement Fermat Factorization Algorithm
Apache Commons Collections SetUtils
Java Program to Solve TSP Using Minimum Spanning Trees
Mệnh đề if-else trong java
Tránh lỗi NullPointerException trong Java như thế nào?
Java Program to Find MST (Minimum Spanning Tree) using Kruskal’s Algorithm
Filtering a Stream of Optionals in Java
Spring Cloud AWS – RDS
Limiting Query Results with JPA and Spring Data JPA
Spring Security Form Login
Java Program to Check whether Directed Graph is Connected using DFS
Remove the First Element from a List
Làm thế nào tạo instance của một class mà không gọi từ khóa new?
Java Program to Implement vector
Java Program to Implement Attribute API
Java Program to Implement Splay Tree
Giới thiệu Swagger – Công cụ document cho RESTfull APIs
Java Program to Create a Random Graph Using Random Edge Generation
Chuyển đổi Array sang ArrayList và ngược lại
Java Program to Implement Queue using Linked List
Call Methods at Runtime Using Java Reflection
Guide to Escaping Characters in Java RegExps
Java Program to Find the Minimum value of Binary Search Tree
Java Program to Implement Max-Flow Min-Cut Theorem
Spring REST with a Zuul Proxy
Java Program to Implement Johnson’s Algorithm
Java Program to Implement Ford–Fulkerson Algorithm
Tạo chương trình Java đầu tiên sử dụng Eclipse
Java Program to Implement Stack
Explain about URL and HTTPS protocol
Java Program to Check Whether an Input Binary Tree is the Sub Tree of the Binary Tree