Почему значение тождества должно быть тождеством функции объединения в Stream.reduce? - PullRequest
5 голосов
/ 31 января 2020

Я учусь Java 8, в Операции сокращения часть в резюме пакета java.util.stream , там написано:

Подробнее формально значение тождества должно быть тождеством функции объединения. Это означает, что для всех u combiner.apply (identity, u) равно u. Кроме того, функция комбинатора должна быть ассоциативной и должна быть совместимой с функцией аккумулятора: для всех u и t combiner.apply (u, аккумулятора.apply (identity, t)) должно быть равно () аккумулятору .apply (u, t).

Я не понимаю, почему значение тождества должно быть тождеством для функции объединителя. Я думаю, что «функция объединения должна быть ассоциативной и должна быть совместимой» достаточно для получения одинакового результата, будь то поток последовательный или параллельный.

Например, у меня есть поток, который имеет четыре элемента e1, e2, e3, e4. Если это последовательный поток, результат будет identity a c e1 a c e2 a c e3 a c e4 (c означает функцию аккумулятора). Если это параллельный поток, четыре элемента могут быть разделены на две части, [e1, e2] и [e3, e4], поэтому получается (identity a c e1 a c e2) co (identity a c e3 a c e4).

Если дано "функция объединителя ассоциативна и совместима с функцией аккумулятора", мы можем сделать вывод, что "identity a c e1 a c e2 a c e3 a c e4 " равно " (identity a c e1 a c e2) co (identity a c e3 a c e4) ":

identity ac e1 ac e2 ac e3 ac e4
= (identity ac e1 ac e2 ac e3) co (identity ac e4) // because of compatibility
= (identity ac e1 ac e2) co (identity ac e3) co (identity ac e4) // because of compatibility
= (identity ac e1 ac e2) co ((identity ac e3) co (identity ac e4)) // because of associative property
= (identity ac e1 ac e2) co ((identity ac e3) ac e4) // because of compatibility
= (identity ac e1 ac e2) co (identity ac e3 ac e4)

Итак, почему идентичность должна значение является идентификатором для функции объединителя?


Вопросы, связанные с данной:

1 Ответ

1 голос
/ 31 января 2020

Я не понимаю, почему значение идентификатора должно быть идентификатором для функции объединения.

Так и должно быть, потому что в противном случае, если предоставленный поток пуст, результат не может быть сгенерированным. Но результат сокращения с идентичностью не является обязательным. Вы можете определить Java 8 сокращение без идентификатор:

OptionalInt sum = Arrays.stream(new int[] { 0, 2, 6 }).reduce((a, b) -> a + b);

Однако, если вы это сделаете, пустой поток не вернет действительный результат, так как операция сокращения не дает 'знать', что 0 является нейтральным элементом определенной вами операции 'сумма'. В математических терминах вы определяете элемент идентификации операции, так что существует запасной вариант, если операция вообще не применима. Визуально вы можете описать операцию следующим образом:

reduction = op (identity, a, b, c ...)

Вот почему вы получаете OptionalInt, то есть, не целое число значение могло быть вычислено.

Для умножения тождество составляет 1, для суммы 0 et c. Поскольку идентичность должна быть нейтральной, это не отступление в самом строгом смысле, так как отступом может быть что угодно, включая -1 или любое другое значение (не должно быть цифрой c единица). Таким образом, OptionalInt предлагает отличную альтернативу, потому что с необязательным вы можете применить метод or(fallback), который не должен быть нейтральным элементом сокращения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...