我无法完全理解 combiner
的作用在 Streams 中实现 reduce
方法。
例如,以下代码无法编译:
int length = asList("str1", "str2").stream()
.reduce(0, (accumulatedInt, str) -> accumulatedInt + str.length());
编译错误说:(参数不匹配;int 不能转换为 java.lang.String)
但这段代码确实可以编译:
int length = asList("str1", "str2").stream()
.reduce(0, (accumulatedInt, str ) -> accumulatedInt + str.length(),
(accumulatedInt, accumulatedInt2) -> accumulatedInt + accumulatedInt2);
我知道在并行流中使用了组合器方法 - 所以在我的例子中,它将两个中间累积整数加在一起。但是我不明白为什么第一个示例在没有组合器的情况下无法编译,或者组合器如何解决 string 到 int 的转换,因为它只是将两个 int 相加。
任何人都可以阐明这一点吗?
最佳答案
reduce
的两个和三个参数版本您尝试使用的 accumulator
不接受相同的类型.
两种说法reduce
是 defined as :
T reduce(T identity,
BinaryOperator<T> accumulator)
在你的情况下,T 是字符串,所以
BinaryOperator<T>
应该接受两个字符串参数并返回一个字符串。但是你传递给它一个 int 和一个 String,这会导致你得到编译错误 - argument mismatch; int cannot be converted to java.lang.String
.实际上,我认为在这里将 0 作为标识值传递也是错误的,因为需要字符串 (T)。另请注意,此版本的reduce 处理Ts 流并返回T,因此您不能使用它来将String 流减少为int。
三论
reduce
是 defined as :<U> U reduce(U identity,
BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
在您的情况下,U 是整数,T 是字符串,因此此方法会将字符串流减少为整数。
对于
BiFunction<U,? super T,U>
accumulator 你可以传递两种不同类型的参数(U 和 ? super T),在你的情况下是整数和字符串。此外,在您的情况下,标识值 U 接受一个 Integer,因此将它传递给 0 就可以了。实现您想要的另一种方法:
int length = asList("str1", "str2").stream().mapToInt (s -> s.length())
.reduce(0, (accumulatedInt, len) -> accumulatedInt + len);
这里流的类型匹配
reduce
的返回类型,所以你可以使用 reduce
的两个参数版本.当然你不必使用
reduce
根本:int length = asList("str1", "str2").stream().mapToInt (s -> s.length())
.sum();
关于java - 为什么在java 8中转换类型的reduce方法需要组合器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24308146/