Потоки на 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]