为什么在java 8中转换类型的reduce方法需要组合器 [英] Why is a combiner needed for reduce method that converts type in java 8

查看:29
本文介绍了为什么在java 8中转换类型的reduce方法需要组合器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法完全理解 combiner 在 Streams reduce 方法中的作用.

I'm having trouble fully understanding the role that the combiner fulfills in Streams reduce method.

例如,以下代码无法编译:

For example, the following code doesn't compile:

int length = asList("str1", "str2").stream()
            .reduce(0, (accumulatedInt, str) -> accumulatedInt + str.length());

编译错误说:(参数不匹配;int 不能转换为 java.lang.String)

但是这段代码确实可以编译:

but this code does compile:

int length = asList("str1", "str2").stream()  
    .reduce(0, (accumulatedInt, str ) -> accumulatedInt + str.length(), 
                (accumulatedInt, accumulatedInt2) -> accumulatedInt + accumulatedInt2);

我知道在并行流中使用组合器方法 - 因此在我的示例中,它将两个中间累积整数相加.

I understand that the combiner method is used in parallel streams - so in my example it is adding together two intermediate accumulated ints.

但我不明白为什么第一个示例在没有组合器的情况下无法编译,或者组合器如何解决字符串到 int 的转换,因为它只是将两个 int 相加.

But I don't understand why the first example doesn't compile without the combiner or how the combiner is solving the conversion of string to int since it is just adding together two ints.

有人能解释一下吗?

推荐答案

您尝试使用的 reduce 的两个和三个参数版本不接受 累加器的相同类型.

The two and three argument versions of reduce which you tried to use don't accept the same type for the accumulator.

两个参数 reduce定义为 :

T reduce(T identity,
         BinaryOperator<T> accumulator)

在你的例子中,T 是字符串,所以 BinaryOperator 应该接受两个字符串参数并返回一个字符串.但是你传递给它一个 int 和一个 String,这会导致你得到编译错误 - argument mismatch;int 不能转换为 java.lang.String.实际上,我认为这里将 0 作为标识值传递也是错误的,因为需要字符串 (T).

In your case, T is String, so BinaryOperator<T> should accept two String arguments and return a String. But you pass to it an int and a String, which results in the compilation error you got - argument mismatch; int cannot be converted to java.lang.String. Actually, I think passing 0 as the identity value is also wrong here, since a String is expected (T).

还要注意这个版本的reduce处理一个Ts流并返回一个T,所以你不能用它来将一个String流减少到一个int.

Also note that this version of reduce processes a stream of Ts and returns a T, so you can't use it to reduce a stream of String to an int.

三个参数 reduce定义为 :

<U> U reduce(U identity,
             BiFunction<U,? super T,U> accumulator,
             BinaryOperator<U> combiner)

在您的情况下,U 是整数,T 是字符串,因此此方法会将字符串流减少为整数.

In your case U is Integer and T is String, so this method will reduce a stream of String to an Integer.

对于 BiFunction accumulator 您可以传递两种不同类型(U 和 ? super T)的参数,在您的情况下是整数和字符串.此外,在您的情况下,标识值 U 接受一个整数,因此将其传递为 0 就可以了.

For the BiFunction<U,? super T,U> accumulator you can pass parameters of two different types (U and ? super T), which in your case are Integer and String. In addition, the identity value U accepts an Integer in your case, so passing it 0 is fine.

实现您想要的另一种方法:

Another way to achieve what you want :

int length = asList("str1", "str2").stream().mapToInt (s -> s.length())
            .reduce(0, (accumulatedInt, len) -> accumulatedInt + len);

这里流的类型与reduce的返回类型匹配,所以可以使用reduce的两个参数版本.

Here the type of the stream matches the return type of reduce, so you can use the two parameter version of reduce.

当然,您根本不必使用 reduce :

Of course you don't have to use reduce at all :

int length = asList("str1", "str2").stream().mapToInt (s -> s.length())
            .sum();

这篇关于为什么在java 8中转换类型的reduce方法需要组合器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆