List.stream, Объясните как работает этот код

List<Integer> list = Arrays.asList(8, 2, 7, 11, 2, 5, 7, 11);
    int a = list.stream().reduce(Integer.MIN_VALUE, (x, y) -> x > y ? x : y);
    int b = list.stream().max((x, y) -> x > y ? x : y).get();
    int c = list.parallelStream().reduce(8, (x, y) -> x > y ? x : y);
    int d = list.stream().reduce(11, (x, y) -> x < y ? x : y);
    int e = list.stream().max(Integer::compare).get();
    int f = list.stream().max(Integer::max).get();

Объясните пожалуйста, что делает каждая строчка кода. И почему получается такой ответ (11, 8, 11, 2, 11, 8)


Ответы (1 шт):

Автор решения: TiBi

a

int a = list.stream().reduce(Integer.MIN_VALUE, (x, y) -> x > y ? x : y);

В этом случае отрабатывает обычный редьюсер. Если кратко, то происходит следующее:

  1. Аккумулятор инициализируется начальнм значением (Integer.MIN_VALUE в данном случае)
  2. Для каждого элемента из list применяется функция переданная 2-м параметром. В нее передается значение аккумулятора и текущий элемент, после чего в аккумулятор сохраняется результат выполнения функции
  3. В конце reduce возвращает значение аккумулятора

В Вашем случае вызовы редьюсера будут примерно такими:

(Integer.MIN_VALUE, 8) -> Integer.MIN_VALUE > 8 ? //возвращается 8
(8, 2) -> 8 > 2 // возвращается 8
(8, 7) -> 8 > 7 // возвращается 8
(8, 11) -> 8 > 11 // возвращается 11
(11, 2) -> 11 > 2 // возвращается 11
(11, 5) -> 11 > 5 // возвращается 11
(11, 7) -> 11 > 7 // возвращается 11
(11, 11) -> 11 > 11  // возвращается 11 и присваивается переменной a

Важно заметить, что разных версях Java порядок вызовов может быть другим, поскольку в документации он не определен

Больше информации по Stream.reduce можно найти в Javadocs, либо поискать что-то в интернете

b

int b = list.stream().max((x, y) -> x > y ? x : y).get();

в метод max передается компаратор, который сравнивает 2 аргумента и возвращает число, которое интерпретируется следующим образом:

  • ноль: оба аргумента равны
  • положительное число: 1-й аргумент больше, чем 2-й
  • отрицательное число: 1-й аргумент меньше, чем 2-й

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

В Вашем случае max берет 2 числа из list, и считает, что 1-е из них большее (в данном случае это 8), поскольку компаратор (x, y) -> x > y ? x : y всегда возвращает положительное число для элементов из list. Далее компаратор последовательно вызывается для текущего максимального и всех остальных элементов.

Стоит отметить, что в документации не определено, какой элемент будет браться 1-м и в каком порядке он будет сравниваться с остальными. В данном случае похоже, что первым взялся элемент 8 и делее он передавался 1-м параметром в вызовы компаратора, поэтому в результате map вернул 8. Теоретически в других версиях Java это поведение может поменяться

c

int c = list.parallelStream().reduce(8, (x, y) -> x > y ? x : y);

По сути то же самое, что и для int a = list.stream().reduce(Integer.MIN_VALUE, (x, y) -> x > y ? x : y), только с другим начальным значением аккумулятора и параллельным стримом

d

int d = list.stream().reduce(11, (x, y) -> x < y ? x : y);

То же, что и для int a = list.stream().reduce(Integer.MIN_VALUE, (x, y) -> x > y ? x : y) только с другим начальным значением и поиском минимального вместо максимального значения

e

int e = list.stream().max(Integer::compare).get();

Аналогично int b = list.stream().max((x, y) -> x > y ? x : y).get();, только используется компаратор, который правильно сравнивает целые числа числа

f

int f = list.stream().max(Integer::max).get();

По сути это то же самое, что и int b = list.stream().max((x, y) -> x > y ? x : y).get(); поскольку Integer::max внутри делает практически то же самое, что и (x, y) -> x > y ? x : y

→ Ссылка