Реализация Java Collectors.reduction

int val = integerList.stream().collect(
        Collectors.reducing(0, a1 -> a1 * 5, (a1, a2) -> a1 + a2));

Приведенный выше код выполняет операцию сокращения. Преобразование потока целых чисел и функции агрегирования для возврата Integer . Я не мог понять приведенный ниже код и внутреннюю реализацию операции сокращения. Как Java может выполнять приведенную ниже функцию Stateful.? Спасибо!

java.util.stream.Collectors:reducing method
    public static <T, U>
    Collector<T, ?, U> reducing(U identity,
                                Function<? super T, ? extends U> mapper,
                                BinaryOperator<U> op) {
        return new CollectorImpl<>(
                boxSupplier(identity),
                (a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); },
                (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
                a -> a[0], CH_NOID);
    }

Может быть, я немного уточню свой вопрос. Как приведенная выше реализация получает поток данных. Относится ли a[0],b[0] к потоку данных? Я считаю, что вышеизложенное обеспечивает функциональную реализацию для поставщика и аккумулятора. Я хотел понять, как работает процесс редукции через код.

Вы ознакомились с документацией? Что там было непонятно?

Naman 03.06.2019 12:57

Документация рассказывает о том, «что» можно сделать. Я ищу разъяснения о том, как это можно сделать.

devv 03.06.2019 13:10

Вы спрашиваете, как работает реализация?

Lino 03.06.2019 13:15

Сейчас можно было бы сказать: «Посмотрите на код класса CollectorImpl», но на самом деле он лишь объединяет данные supplier, accumulator, combiner и finisher, а вся магия происходит в реализации ReferencePipeline. Кроме того, вам нужно будет более четко сказать, в чем заключается вопрос (также см. docs.oracle.com/javase/tutorial/collections/streams/… , если вы еще этого не сделали)

Marco13 03.06.2019 13:18

Несмотря на то, что код JVM хорошо написан, его часто трудно читать из-за уровня абстракции и сложности. Вы должны быть очень конкретными. «внутренняя реализация операции сокращения» четко не определена.

Andrew Tobilko 03.06.2019 13:19

«Как Java может выполнять приведенную ниже функцию Stateful?» a и b — это массивы T[], в которых сохраняется промежуточное состояние

Andrew Tobilko 03.06.2019 13:21

Да @Lino. Я спрашиваю о реализации

devv 03.06.2019 13:52

Спасибо @Marco13 и Эндрю Тобилико. ReferencedPipeline — хороший лидер. Вероятно, мне следует больше узнать о классе StreamSupport. Вот что я имел в виду Внутренняя реализация. Прежде чем я понял, получил голоса

devv 03.06.2019 13:54
developer.ibm.com/articles/j-java-streams-3-brian-goetz Эта ссылка очень полезна
devv 03.06.2019 14:06

Вы должны посмотреть на пакетная документация. Он показывает простой эквивалентный код для объяснения логики.

Holger 04.06.2019 13:27
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
10
6 513
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Функция принимает три аргумента:

  • Первый — это личность. При сокращении потока нужно с чего-то начинать (иначе, какой будет результат сокращения пустого списка?). Идентификатор — это объект, применяемый к первому аргументу первой операции редукции в цепочке.

  • Второй — картограф. reducing() — это обобщенная операция — вы можете свести элементы потока типа T к конечному результату типа U, поэтому вам нужно дать промежуточную операцию, которая предоставляет элемент типа U из элемента типа T. Если T == U и вы не хотите преобразования, вы можете указать здесь функцию идентификации

  • Третий аргумент — функция редукции — она применяется к элементам потока последовательно, начиная с личность.

Итак, в качестве примера:

Если вы хотите просто суммировать элементы потока Integer в целое число, вы можете использовать Collectors.reducing(0, x -> x, (x, y) -> x + y).

Если вы хотите суммировать длины String в потоке String, вы можете использовать Collectors.reducing(0, String::length, (x, y) -> x + y).

Если вы хотите получить максимум Double из строки Doubles, но не меньше Math.PI, вы можете использовать Collectors.reducing(Math.PI, x -> x, Math::max).

Кроме того, если вы хотите, чтобы ваша редукция сохраняла состояние, помните, что вы можете использовать в качестве редуктора ссылку на метод внутри объекта. Таким образом, объект можно использовать для сохранения состояния. Например, вот «уменьшитель налогов», который добавляет 1 «налог» к своему счету каждые 100 добавлений:

public class Taxer implements BinaryOperator<Integer> {
 int counter = 0;

 @Override
 public Integer apply(Integer i1, Integer i2) {
  counter++;
  if (counter % 100 == 0) {
   return i1 + i2 + 1;
  } else {
   return i1 + i2;
  }
 }
}

...

Taxer t = new Taxer();

...

.collect(Collectors.reducing(0, x -> x, t);

То же самое можно расширить, используя для реализации сложных случаев, таких как groupingBy:

Map<String, Integer> output = Stream.of("this", "word", "is", "the", "best")
    .collect(Collectors.groupingBy(x-> x.substring(0, 1),
            Collectors.reducing(0, x-> x.length(), (x, y)-> x + y)));

Здесь сначала входная строка группируется на основе символа, с которого она начинается, а затем суммируются длины

Отличный ответ, 3 балла помогли мне пройти. У меня возникла проблема с GroupBy с уменьшением. Я также добавил образец в ваш код. +1 за 3 балла ура

iam.Carrot 10.01.2020 05:49

Спасибо за отличный ответ. Я понял уменьшающую операцию. (Чем просто зная).

devv 12.07.2020 05:24

Спасибо за вотум доверия, приятно знать, что это было действительно полезно :>

Piotr Wilkin 30.07.2020 10:50

Другие вопросы по теме