Java Stream Filter with Lambda Expression – 使用Lambda表达式的Java流过滤器

最后修改: 2018年 12月 12日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

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

在这个快速教程中,我们将探讨在Java中使用Streams方法的使用。

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

我们将研究如何使用它,以及如何处理有检查异常的特殊情况。

2. Using Stream.filter()

2.使用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:

filter()方法是Stream接口的一个中间操作,它允许我们过滤一个流中符合给定Predicate的元素:

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

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

为了了解这一点,让我们创建一个Customer类。

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

2.1.筛选集合

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

filter()方法的一个常见用例是处理集合

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

让我们做一个超过100分的客户列表。点。要做到这一点,我们可以使用一个lambda表达式。

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:

我们还可以使用方法引用,这是lambda表达式的简写。

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

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

在这种情况下,我们将hasOverHundredPoints方法添加到我们的Customer类。

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

2.2.用多个标准过滤集合

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

此外,我们可以用filter()来使用多个条件。例如,我们可以通过pointsname过滤。

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

3.处理异常

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.

到目前为止,我们一直在用不抛出异常的谓词来使用这个过滤器。事实上,Java中的功能接口并没有声明任何检查或未检查的异常

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

接下来我们将展示一些处理lambda表达式中的异常的不同方法

3.1. Using a Custom Wrapper

3.1.使用自定义封装器

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

首先,我们将开始为我们的客户添加profilePhotoUrl :。

private String profilePhotoUrl;

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

此外,让我们添加一个简单的hasValidProfilePhoto()方法来检查配置文件的可用性。

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:

我们可以看到,hasValidProfilePhoto()方法抛出了一个IOException。现在,如果我们尝试用这个方法来过滤客户。

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:

为了处理这个问题,我们可以使用的一个替代方法是用一个try-catch块来包装它。

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.

如果我们需要从我们的谓词中抛出一个异常,我们可以把它包装在一个未检查的异常中,比如RuntimeException

3.2. Using ThrowingFunction

3.2.使用抛出函数

Alternatively, we can use the ThrowingFunction library.

另外,我们可以使用ThrowingFunction库。

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

ThrowingFunction是一个开源的库,它允许我们在Java函数式接口中处理检查过的异常。

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

让我们先把throwing-function依赖项添加到我们的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.

为了处理谓词中的异常,这个库为我们提供了ThrowingPredicate类,它有unchecked()方法来包裹检查的异常。

Let’s see it in action:

让我们看看它的行动。

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

4. Conclusion

4.结论

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.

在这篇文章中,我们看到了一个如何使用filter()方法来处理流的例子。我们还探讨了一些处理异常的替代方法。

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

一如既往,完整的代码可在GitHub上获得