如何用java流汇总整数列表?

时间:2015-05-08 13:39:10

标签: java java-8 java-stream

我想总结一个整数列表。它的工作原理如下,但语法感觉不对。代码可以优化吗?

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

12 个答案:

答案 0 :(得分:436)

这样可行,但i -> i正在做一些自动拆箱,这就是为什么它会感觉到#34;奇怪。下面的任何一个都可以使用原始语法更好地解释编译器在做什么:

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

答案 1 :(得分:138)

我建议另外两个选择:

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

答案 2 :(得分:80)

来自docs

  

减少操作   缩减操作(也称为折叠)采用一系列输入元素,并通过重复应用组合操作将它们组合成单个汇总结果,例如查找一组数字的总和或最大值,或将元素累积到列表中。流类具有多种形式的通用缩减操作,称为reduce()和collect(),以及多种专用缩减形式,如sum(),max()或count()。

     

当然,这样的操作可以很容易地实现为简单的顺序循环,如:

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

然而,有充分的理由选择减少操作而不是如上所述的变异累积。减少&#34;更抽象&#34; - 它作为一个整体而不是单个元素在流上运行 - 但正确构造的reduce操作本质上是可并行化的,只要用于处理元素的函数是关联的和无状态的。例如,给定我们想要找到总和的数字流,我们可以写:

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

答案 3 :(得分:26)

您可以使用reduce方法:

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

答案 4 :(得分:14)

您可以使用reduce()对整数列表求和。

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

答案 5 :(得分:10)

您可以使用collect方法添加整数列表。

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

答案 6 :(得分:3)

这是总结int类型数组(对于long数组LongStreamdouble数组DoubleStream等的最短方法)。但是,并非所有原始整数或浮点类型都具有Stream实现。

IntStream.of(integers).sum();

答案 7 :(得分:1)

这可以帮助那些在列表上有对象的人。

如果您有对象列表,并且想要汇总该对象的特定字段,请使用以下内容。

List<ResultSom> somList = MyUtil.getResultSom();
BigDecimal result= somList.stream().map(ResultSom::getNetto).reduce(
                                             BigDecimal.ZERO, BigDecimal::add);

答案 8 :(得分:0)

我已经声明了一个整数列表。

ArrayList<Integer> numberList = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));

您可以在下面尝试使用这些不同的方式。

使用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 :(得分:0)

不幸的是,Stream API 只返回来自 List<Integer>#stream() 的普通流。猜猜他们是被迫的,因为泛型是如何工作的。

这些普通的流是通用对象,所以没有像 sum() 等专门的方法,所以你必须默认使用奇怪的重新流“看起来像一个无操作”转换来获得那些方法....mapToInt(i -> i)

另一种选择是使用“Eclipse Collections”,它类似于扩展的 Java Stream API

IntLists.immutable.ofAll(integers.values()).sum();

答案 10 :(得分:-1)

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

答案 11 :(得分:-1)

涵盖了大多数方面。但是可能需要找到除Integer Long以外的其他数据类型的聚合(已提供专用流支持)。例如与BigInteger合作 对于这种类型,我们可以使用诸如

这样的reduce操作

list.stream()。reduce((bigInteger1,bigInteger2)-> bigInteger1.add(bigInteger2))