我想对整数列表进行求和。以下是代码示例,但语法不太对。这段代码能否进行优化?
Map<String, Integer> integers;
integers.values().stream().mapToInt(i -> i).sum();
我想对整数列表进行求和。以下是代码示例,但语法不太对。这段代码能否进行优化?
Map<String, Integer> integers;
integers.values().stream().mapToInt(i -> i).sum();
这样做是可行的,但i -> i
执行了一些自动拆箱操作,这就是为什么它“感觉”奇怪的原因。mapToInt
将流转换为“基本int值元素”的IntStream
。以下任何一个都可以工作,并更好地解释编译器在使用原始语法时正在执行的操作:
integers.values().stream().mapToInt(i -> i.intValue()).sum();
integers.values().stream().mapToInt(Integer::intValue).sum();
BigDecimal sum = numbers.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
。该代码使用Java 8中的流式编程,对一个包含BigDecimal数字的列表进行求和操作,并将结果存储在变量sum中。其中,方法reduce()的第一个参数表示初始值为0,第二个参数则是用于累加的函数BigDecimal::add。 - Matt我建议再增加两个选项:
integers.values().stream().mapToInt(Integer::intValue).sum();
integers.values().stream().collect(Collectors.summingInt(Integer::intValue));
第二种方法使用Collectors.summingInt()
收集器,还有一个summingLong()
收集器可用于与mapToLong
一起使用。
LongAdder
累加器,旨在加速并行流和多线程环境下的汇总。这里是一个示例用法:LongAdder a = new LongAdder();
map.values().parallelStream().forEach(a::add);
sum = a.intValue();
来自文档
归约操作 归约操作(也叫折叠操作)将一系列输入元素通过重复应用一个组合操作,例如找到一组数字的总和或最大值,或将元素累积到列表中,将它们组合成单个摘要结果。流类具有多种形式的通用归约操作,称为reduce()和collect(),以及多个专门的归约形式,如sum()、max()或count()。
当然,这样的操作可以轻松地实现为简单的顺序循环,就像:
int sum = 0;
for (int x : numbers) {
sum += x;
}
然而,有很多好的理由选择reduce操作而不是像上面那样进行可变的累加。不仅reduce“更抽象”——它作用于整个流而不是单个元素——而且正确构建的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);
你可以使用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);
int
的这样的累加器,它是 Integer::sum
。 - Alex SalauyouLong::sum
而不是 Integer::sum
。 - Andrei Damian-Fekete你可以使用reduce()
函数来对一个整数列表求和。
int sum = integers.values().stream().reduce(0, Integer::sum);
List<Integer> list = Arrays.asList(2, 4, 5, 6);
int sum = list.stream().collect(Collectors.summingInt(Integer::intValue));
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();
希望这篇文章能够帮助那些需要对列表中的对象进行操作的人。
如果你有一个对象列表,并且想要对其中特定字段进行求和,请使用以下方法。
List<ResultSom> somList = MyUtil.getResultSom();
BigDecimal result= somList.stream().map(ResultSom::getNetto).reduce(
BigDecimal.ZERO, BigDecimal::add);
IntStream.of(integers).sum();
IntStream.of(integers.values().stream().mapToInt(Integer::intValue).toArray())。sum();
- Kaplanintegers.values().stream().mapToInt( Integer::intValue ).sum()
。 - Sachith Dickwella这里还有一个选项,与多核环境的使用有关。如果您想利用它的优势,那么应该使用下面的代码而不是其他提到的解决方案:
int sum = integers.values().parallelStream().mapToInt(Integer::intValue)
.reduce(0, Integer::sum, Integer::sum);
parallelStream()
而不是 stream()
。在这种情况下,它只会对其进行汇总。作为第三个参数放置的另一个选项是 (i, j) -> i + j
,这意味着它将把流块的值(j
)添加到当前值(i
)并将其用作下一个流块的当前值,直到处理完所有部分结果。stream()
,也有必要告诉 reduce 如何处理流块的汇总,以防以后有人或您想并行化它。最初的开发是最好的时机,因为以后您需要记住这是什么,并需要花费一些时间来理解该代码的目的。
mapToLong
来避免溢出。 - Alexis C.foo(int i)
的人不会每次调用它时都写foo(myInteger.intValue());
(或者至少我希望如此!!)。我同意您的看法,即Integer::intValue
更加明确,但我认为同样适用于这里。人们只需要学习一次,然后就完成了 :-)。这不像是一些神奇的混淆技术。 - Alexis C.Integer.intValue()
方法,但更深入底层,该方法会被内联成与源代码中看起来完全一样的no-op。 使用Integer :: intValue
有额外的好处,即不会在字节码中创建合成方法,但这不应驱动您决定如何组织源代码。 - Holger