Рубрики
Без рубрики

Фильтр потока Java с лямбда-выражением

Узнайте, как использовать лямбда-выражения с Stream.filter() и обрабатывать проверенные исключения

Автор оригинала: baeldung.

1. введение

В этом кратком руководстве мы рассмотрим использование метода Stream.filter() при работе с потоками в Java .

Мы рассмотрим, как его использовать и как обрабатывать особые случаи с проверенными исключениями.

Дальнейшее чтение:

Введение в потоки Java 8

Как отфильтровать коллекцию в Java

Функциональные интерфейсы в Java 8

2. Использование Stream.filter()

Метод filter() является промежуточной операцией интерфейса Stream , которая позволяет нам фильтровать элементы потока, соответствующие заданному Предикату:

Stream filter(Predicate predicate)

Чтобы увидеть, как это работает, давайте создадим класс Customer :

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

Кроме того, давайте создадим коллекцию клиентов:

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 customers = Arrays.asList(john, sarah, charles, mary);

2.1. Фильтрация Коллекций

Общим случаем использования метода filter() является обработка коллекций .

Давайте составим список клиентов с более чем 100 баллами. Для этого мы можем использовать лямбда – выражение:

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

Мы также можем использовать ссылку на метод , которая является сокращением для лямбда – выражения:

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

В этом случае мы добавили метод имеет более ста баллов в наш Клиент класс:

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

В обоих случаях мы получаем один и тот же результат:

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

2.2. Фильтрация коллекций по нескольким критериям

Кроме того, мы можем использовать несколько условий с filter() . Например, мы можем фильтровать по точкам и имени :

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

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

3. Обработка Исключений

До сих пор мы использовали фильтр с предикатами, которые не создают исключения. Действительно, функциональные интерфейсы в Java не объявляют никаких проверенных или непроверенных исключений .

Далее мы покажем несколько различных способов обработки исключений в лямбда-выражениях .

3.1. Использование пользовательской оболочки

Во-первых, мы начнем с добавления Url-адреса фотографии профиля к нашему Клиенту :

private String profilePhotoUrl;

Кроме того, давайте добавим простой имеет действительную фотографию профиля() метод проверки доступности профиля:

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

Мы видим, что метод имеет допустимую фотографию профиля() вызывает исключение IOException . Теперь, если мы попытаемся отфильтровать клиентов с помощью этого метода:

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

Мы увидим следующую ошибку:

Incompatible thrown types java.io.IOException in functional expression

Чтобы справиться с этим, одна из альтернатив, которую мы можем использовать,-это обернуть его блоком try-catch:

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

Если нам нужно создать исключение из нашего предиката, мы можем обернуть его в непроверенное исключение, например Исключение RuntimeException .

3.2. Использование Функции Метания

В качестве альтернативы мы можем использовать библиотеку функций метания.

Функция ThrowingFunction-это библиотека с открытым исходным кодом, которая позволяет нам обрабатывать проверенные исключения в функциональных интерфейсах Java.

Давайте начнем с добавления метательной функции зависимости в наш pom:


    pl.touk
    throwing-function
    1.3

Для обработки исключений в предикатах эта библиотека предлагает нам класс Throwing Predicate , который имеет метод unchecked() для переноса проверенных исключений.

Давайте посмотрим на это в действии:

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

4. Заключение

В этой статье мы рассмотрели пример того, как использовать метод filter() для обработки потоков. Мы также рассмотрели некоторые альтернативы для обработки исключений.

Как всегда, полный код доступен на GitHub .