Java中与Python的reduce函数相对应的是什么?

6
类似的问题已经被问过了,这里这里,但是考虑到Java 8的出现以及这些问题通常过时的情况,我想知道现在是否至少有类似的东西?

这就是我所指的。


使用Stream.collect能够提供更好的性能,因此或许可以考虑一下它呢? - Marko Topolnik
虽然Java的reduce与Python的等效,但它不如Python灵活。例如,您不能提供不同类型的初始值,并基于当前结果和流中的元素进行顺序缩减。因为您还需要提供一个组合器双函数,应该提供一致的结果,例如a+b=b+a - ahanin
3个回答

5
您可以使用lambda表达式和Stream.reduce方法进行操作,Java文档中有一整页专门介绍reductions操作:reductions
Integer totalAgeReduce = roster
   .stream()
   .map(Person::getAge)
   .reduce(
       0,
       (a, b) -> a + b);

4
这是使用Java 8流实现的 Python文档中示例
List<Integer> numbers = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5 });
Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);
System.out.println(sum.get());

从OP链接的页面(https://docs.python.org/2/library/functions.html#reduce)中,@zehnpaard`reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])`。 - Sylwester
啊,抱歉我误解了,我以为你的意思是Java代码在Python文档中出现过,或许作为其他语言类似技术比较的一部分。 - zehnpaard

3

Stream.reduce 方法

Stream.reduce 方法是通用的归约操作。考虑以下管道,它计算集合花名册中男性成员年龄的总和。它使用了 Stream.sum 归约操作:

 Integer totalAge = roster
     .stream()
    .mapToInt(Person::getAge)
    .sum();

将以下管道与使用Stream.reduce操作计算相同值的管道进行比较:

Integer totalAgeReduce = roster
   .stream()
   .map(Person::getAge)
   .reduce(
       0,
       (a, b) -> a + b);

在这个例子中,reduce操作需要两个参数:
identity:身份元素既是规约的初始值,也是如果流中没有元素时的默认结果。在这个例子中,身份元素是0;这是年龄总和的初始值,如果集合名单中不存在成员,则为默认值。
accumulator:累加器函数使用两个参数:一个部分规约结果(在这个例子中是到目前为止处理的所有整数的和)和流的下一个元素(在这个例子中是一个整数)。它返回一个新的部分结果。在这个例子中,累加器函数是一个Lambda表达式,它将两个整数值相加并返回一个整数值:
(a, b) -> a + b

reduce操作总是返回一个新值。但是,累加器函数也在处理流的元素时每次返回一个新的值。假设你想将流的元素缩减到一个更复杂的对象(如集合)中,这可能会影响你的应用程序性能。如果你的reduce操作涉及向集合添加元素,则每次累加器函数处理一个元素时,它都会创建一个包含该元素的新集合,这是低效的。相对来说,更新现有集合会更有效率。你可以使用Stream.collect方法来实现这一点,下一节将对其进行描述。
官方Oracle教程介绍了Stream.reduce的工作原理。请看一下,我相信它会回答你的疑问。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接