Потоки на Java не могут понять этот код
Я нашел следующий фрагмент кода:
Function<Integer, Predicate<Integer>> smallerThan = x -> y -> y < x;
List<Integer> l = Arrays.asList(5, 6, 7, 23, 4, 5645,
6, 1223, 44453, 60182, 2836, 23993, 1);
List<Integer> list2 = l.stream()
.filter(smallerThan.apply(l.get(0)))
.collect(Collectors.toList());
System.out.println(list2);
В качестве вывода я получаю:
[4, 1]
Как работает функция smallerThan
в этом примере, учитывая, что мы передаем только один параметр smallerThan.apply(l.get(0))
?
Ответы
Ответ 1
smallerThan
является Function
, который принимает один Integer
и возвращает a Predicate<Integer>
(a Predicate<Integer>
- это функция, которая принимает один Integer
и возвращает a boolean
).
smallerThan.apply(l.get(0))
возвращает a Predicate<Integer>
, который выглядит следующим образом:
y -> y < l.get(0)
то есть. он возвращает true
, если введенный ему вход меньше, чем l.get(0)
.
Когда вы передаете этот Predicate
в filter
, ваш конвейер Stream
содержит только те элементы, которые меньше l.get(0)
.
Ваш трубопровод можно переписать как:
List<Integer> list2 = l.stream()
.filter(y -> y < l.get(0))
.collect(Collectors.toList());
Так как l.get(0)
- 5
, ваш конвейер возвращает все элементы исходного списка меньше 5
.
Ответ 2
Это называется "currying", и это было возможно и до Java 8 через анонимные классы, но это было гораздо более подробным. В конечном счете, он Function
, который возвращает Function
, и хотя это не распространяется на Java (пока), на других функциональных языках он используется довольно сильно.
Ответ 3
Функция smallerThan
принимает число и возвращает объект Predicate
, и в этом случае мы применяем этот предикат к каждому элементу потока.
Итак, l.get(0)
будет извлекать первое значение списка l
, которое (5)
, затем передаем его функции smallerThan
, и эта функция возвращает предикат с критериями y -> y < x;
, который читается как "если задано число, верните true, если оно меньше 5", следовательно, вывод [4, 1]