BinaryOpertor for List <Integer>для добавления списков - PullRequest
0 голосов
/ 24 декабря 2018

В предыдущем вопросе, который я задавал ранее Какой FunctionalInterface я должен использовать?

Теперь я пытался добавить к List<Integer>, а не просто к двум Целым числам a и b, так что каждый индекс добавляет к тому же индексу другого списка.

Ранее у меня было

 BinaryOperator<Integer> binaryOperator = Integer::sum;

для добавления двух целых чисел с помощью binaryOperator.apply(int a,int b).Есть ли такой же способ, как

BinaryOperator<List<Integer>> binaryOperator = List<Integer>::sum;

, а затем получить результат в List<Integer> cList?

Ответы [ 3 ]

0 голосов
/ 24 декабря 2018

, если вы хотите выполнить некоторые вычисления для элементов с соответствующими индексами (в данном конкретном случае - суммированием), нет необходимости использовать BinaryOperator, вместо этого используйте IntStream.range для генерации индексов:

// generates numbers from 0 until list.size exclusive 
IntStream.range(0, list.size())....

// generates numbers from 0 until the minimum of the two lists exclusive if needed
IntStream.range(0, Math.min(list.size(), list2.size()))....

Общее название для этого типа логики "zip";т.е. когда даны две входные последовательности, он создает выходную последовательность, в которой каждые два элемента из входных последовательностей в одной и той же позиции объединяются с использованием некоторой функции.

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

, используя метод zip в принятом ответе связанного сообщения, вы можете просто сделать:

List<Integer> result = zip(f.stream(), s.stream(), (l, r) -> l + r).collect(toList());

или использовать ссылку на метод:

List<Integer> result = zip(f.stream(), s.stream(), Math::addExact).collect(toList());

, где f и s - ваш список целых чисел.

0 голосов
/ 24 декабря 2018

Что вы можете сделать, это определить свой собственный служебный метод, единственной задачей которого является архивирование двух списков ввода:

<T> List<T> zip(final List<? extends T> first, final List<? extends T> second, final BinaryOperator<T> operation)
{
    return IntStream.range(0, Math.min(first.size(), second.size()))
        .mapToObj(index -> operation.apply(first.get(index), second.get(index)))
        .collect(Collectors.toList());
}

Таким образом, вы можете суммировать два списка ввода как:

zip(first, second, Integer::sum)
0 голосов
/ 24 декабря 2018

Вы можете использовать IntStream.range() для перебора элементов, затем mapToObj() для сопоставления их с их суммой и collect() в третьем списке.

Учитывая, что ваши списки имеют того же размера

List<Integer> first = List.of(); // initialised
List<Integer> second = List.of(); // initialised

Вы можете получить третий список как:

List<Integer> third = IntStream.range(0, first.size())
                               .mapToObj(i -> first.get(i) + second.get(i))
                               .collect(Collectors.toList());

С точки зрения BinaryOperator, вы можете представить его как:

BinaryOperator<List<Integer>> listBinaryOperator = (a, b) -> IntStream.range(0, first.size())
            .mapToObj(i -> first.get(i) + second.get(i))
//          OR from your existing code
//          .mapToObj(i -> binaryOperator.apply(first.get(i), second.get(i)))
            .collect(Collectors.toList());

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

BinaryOperator<List<Integer>> listBinaryOperator = YourClass::sumOfList;

, где sumOfList определяется как:

private List<Integer> sumOfList(List<Integer> first, List<Integer> second) {
    return IntStream.range(0, first.size())
            .mapToObj(i -> first.get(i) + second.get(i))
            .collect(Collectors.toList());
}
...