Интерфейс Java 8 Stream представляет метод filter() который можно использовать для фильтрации некоторых элементов из коллекции объектов на основе определенного условия. Это условие должно быть указано как предикат, который метод filter() принимает в качестве аргумента.
Интерфейс java.util.function.Predicate определяет абстрактный метод с именем test() который принимает объект универсального типа T и возвращает логическое значение.
Давайте сделаем некоторое кодирование, чтобы понять метод фильтра более четко. Посмотрите на следующий класс Блюдо.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public class Dish { private String name; private Boolean vegitarian; private Integer calaries; private Type type; public Dish(String name, Boolean vegitarian, Integer calaries, Type type) { super(); this.name = name; this.vegitarian = vegitarian; this.calaries = calaries; this.type = type; } public Boolean getVegitarian() { return vegitarian; } public void setVegitarian(Boolean vegitarian) { this.vegitarian = vegitarian; } public Type getType() { return type; } public void setType(Type type) { this.type = type; } public enum Type { MEAT, FISH, OTHER };} |
Давайте подумаем, мы хотим отфильтровать только вегетарианские блюда из списка всех блюд. Ниже приводится подход до Java 8.
|
1
2
3
4
5
6
|
List<Dish> vegetarianDishes = new ArrayList<Dish>(); for(Dish d: menu) { if(d.getVegetarian()) { vegetarianDishes.add(d); } } |
Вышеуказанный подход называется внешней итерацией, которой мы явно управляем итерацией по сбору данных.
Как это можно сделать с Java 8? Это просто вопрос одной строки следующим образом.
|
1
2
3
4
|
List<Dish> menu = ....List<Dish> vegitarianDishes = menu.stream() .filter(d -> d.getVegitarian()) .collect(Collectors.toList()); |
Мы передали экземпляр Predicate в метод filter() в форме лямбда-выражения.
Кроме того, мы можем использовать ссылки на метод java 8 для передачи экземпляра Predicate методу filter() следующим образом.
|
1
2
3
4
|
List<Dish> menu = ....List<Dish> vegitarianDishes = menu.stream() .filter(Dish::getVegitarian) .collect(Collectors.toList()); |
Dish::getVegitarian — это синтаксис для ссылок на методы Java 8. Это относится к getVegitarian() класса Dish.
Метод filter() возвращает Stream of Dishes, а метод collect() преобразует Stream в список. Операция сбора называется операцией терминала.
Допустим, мы хотим получить первые три блюда, которые содержат более 300 калорий. Потоки поддерживают метод limit(n) , который возвращает другой поток, длина которого не превышает заданный размер. Запрашиваемый размер передается в качестве аргумента для ограничения.
|
1
2
3
4
5
|
List<Dish> menu = ....List<Dish> threeHighCalaricDish = menu.stream() .filter(d -> d.getCalaries() > 300) .limit(3) .collect(Collectors.toList()); |
Точно так же, если мы хотим пропустить первые 3 элемента, потоки поддерживают метод skip(n) для возврата потока, который отбрасывает первые n элементов. Если в потоке меньше элементов, чем n, возвращается пустой поток. Обратите внимание, что limit(n) и skip(n) дополняют друг друга!
Теперь упражнение для вас! Как бы вы использовали потоки для фильтрации первых двух мясных блюд?
|
1
2
3
4
5
|
List<Dish> menu = ....List<Dish> meatDishes = menu.stream() .filter(d -> d.getType() == Dish.Type.MEAT) .limit(2) .collect(Collectors.toList()) |
| Опубликовано на Java Code Geeks с разрешения Семики Калуге, партнера нашей программы JCG. Смотрите оригинальную статью здесь: Как использовать метод filter () в Java 8
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |