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

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

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

Ответ 1

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

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

Ответ 2

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

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

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


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

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

Ответ 3

Из 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);

Ответ 4

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

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);

Ответ 5

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

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

Ответ 6

Вы можете использовать метод сбора, чтобы добавить список целых чисел.

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

Ответ 7

Это был бы кратчайший способ суммировать массив типа int (для long массива LongStream, для double массива DoubleStream и т.д.). Однако не все примитивные целочисленные типы или типы с плавающей запятой имеют реализацию Stream.

IntStream.of(integers).sum();

Ответ 8

Вы можете попробовать использовать их ниже:

Использование mapToInt

int sum = numberList.stream().mapToInt(Integer::intValue).sum();

Используя summarizingInt

int sum = numberList.stream().collect(Collectors.summarizingInt(Integer::intValue)).getSum();

Используя reduce

int sum = numberList.stream().reduce(Integer::sum).get().intValue();

Ответ 9

class Pojo{
    int num;

    public Pojo(int num) {
        super();
        this.num = num;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

List<Pojo> list = new ArrayList<Pojo>();
            list.add(new Pojo(1));
            list.add(new Pojo(5));
            list.add(new Pojo(3));
            list.add(new Pojo(4));
            list.add(new Pojo(5));

            int totalSum = list.stream().mapToInt(pojo -> pojo.getNum()).sum();
            System.out.println(totalSum);

Ответ 10

Большинство аспектов покрыты. Но может возникнуть необходимость найти агрегацию других типов данных, кроме Integer, Long (для которых уже есть поддержка специализированных потоков). Например, для Stram с BigInteger. Для такого типа мы можем использовать операцию

list.stream(). Reduce ((bigInteger1, bigInteger2) → bigInteger1.add(bigInteger2))