Как суммировать список целых чисел с потоками java?



Я хочу суммировать список целых чисел. Работает это следующим образом, но синтаксис не очень хорошо. Можно ли оптимизировать код?



Map<String, Integer> integers;
integers.values().stream().mapToInt(i -> i).sum();
1371   6  

6 ответов:

это будет работать, но i -> i делает некоторые автоматические распаковки, поэтому он" чувствует " странно. Любое из следующих действий будет работать и лучше объяснить, что компилятор делает под капотом с вашим исходным синтаксисом:

integers.values().stream().mapToInt(i -> i.intValue()).sum();
integers.values().stream().mapToInt(Integer::intValue).sum();

Я предлагаю еще 2 варианта:

integers.values().stream().mapToInt(Integer::intValue).sum();
integers.values().stream().collect(Collectors.summingInt(Integer::intValue));

второй использует Collectors.summingInt() коллектор, есть также summingLong() коллектор, который вы бы использовали с mapToLong.


и третий вариант: Java 8 вводит очень эффективный LongAdder аккумулятор предназначен для ускорения суммирования в параллельных потоках и многопоточных средах. Вот пример использования:

LongAdder a = new LongAdder();
map.values().parallelStream().forEach(a::add);
sum = a.intValue();

С docs

операции по уменьшению Операция сокращения (также называемая сгибом) принимает последовательность входных элементов и объединяет их в один суммарный результат путем повторного применения операции объединения, такой как нахождение суммы или максимума набора чисел или накопление элементов в список. Классы потоков имеют несколько форм общих операций сокращения, называемых reduce () и collect (), а также несколько специализированных формы сокращения, такие как sum (), max () или count().

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

int sum = 0;
for (int x : numbers) {
   sum += x;
}

тем не менее, есть веские причины предпочесть операцию уменьшения над мутационным накоплением, таким как выше. Мало того, что сокращение "более абстрактно" - оно работает на потоке в целом, а не на отдельных элементах-но правильно построенная операция сокращения по своей сути распараллеливается, так долго поскольку функции, используемые для обработки элементов, являются ассоциативными и не имеют состояния. Например, учитывая поток чисел, для которых мы хотим найти сумму, мы можем написать:

int sum = numbers.stream().reduce(0, (x,y) -> x+y);

или:

int sum = numbers.stream().reduce(0, Integer::sum);

эти операции сокращения могут безопасно выполняться параллельно почти без изменений:

int sum = numbers.parallelStream().reduce(0, Integer::sum);

Итак, для карты вы бы использовали:

integers.values().stream().mapToInt(i -> i).reduce(0, (x,y) -> x+y);

или:

integers.values().stream().reduce(0, Integer::sum);

Вы можете использовать метод сокращения:

long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, (x, y) -> x + y);

или

long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, Integer::sum);

вы можете использовать метод collect для добавления списка целых чисел.

List<Integer> list = Arrays.asList(2, 4, 5, 6);
int sum = list.stream().collect(Collectors.summingInt(Integer::intValue));

можно использовать reduce() для суммирования списка целых чисел.

int sum = integers.values().stream().reduce(0, Integer::sum);

Comments

    Ничего не найдено.