1. введение
В этом кратком руководстве мы рассмотрим использование метода Stream.filter() при работе с потоками в Java .
Мы рассмотрим, как его использовать и как обрабатывать особые случаи с проверенными исключениями.
Дальнейшее чтение:
Введение в потоки Java 8
Как отфильтровать коллекцию в Java
Функциональные интерфейсы в Java 8
2. Использование Stream.filter()
Метод filter() является промежуточной операцией интерфейса Stream , которая позволяет нам фильтровать элементы потока, соответствующие заданному Предикату:
Streamfilter(Predicate super T> 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); Listcustomers = Arrays.asList(john, sarah, charles, mary);
2.1. Фильтрация Коллекций
Общим случаем использования метода filter() является обработка коллекций .
Давайте составим список клиентов с более чем 100 баллами. Для этого мы можем использовать лямбда – выражение:
ListcustomersWithMoreThan100Points = customers .stream() .filter(c -> c.getPoints() > 100) .collect(Collectors.toList());
Мы также можем использовать ссылку на метод , которая является сокращением для лямбда – выражения:
ListcustomersWithMoreThan100Points = 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() . Например, мы можем фильтровать по точкам и имени :
ListcharlesWithMoreThan100Points = 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 . Теперь, если мы попытаемся отфильтровать клиентов с помощью этого метода:
ListcustomersWithValidProfilePhoto = customers .stream() .filter(Customer::hasValidProfilePhoto) .collect(Collectors.toList());
Мы увидим следующую ошибку:
Incompatible thrown types java.io.IOException in functional expression
Чтобы справиться с этим, одна из альтернатив, которую мы можем использовать,-это обернуть его блоком try-catch:
ListcustomersWithValidProfilePhoto = 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 .