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

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

问题描述

我无法完全理解组合器在Streams reduce 方法中完成的角色。



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

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

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



但这段代码确实编译:

  int length = asList(str1,str2)。stream()
.reduce(0,(cumulativeInt,str) - > cumulativeInt + str.length(),
(cumulativeInt,cumulativeInt2) - > cumulativeInt + cumulativeInt2);

我知道组合器方法用于并行流 - 所以在我的例子中它是将两个加在一起中间积累的整数。



但是我不明白为什么第一个例子在没有组合器的情况下编译或者组合器如何解决字符串到int的转换,因为它只是将两个整数加在一起。 / p>

有人能说清楚这个吗?

解决方案

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



两个参数 reduce 定义为

  T reduced(T identity,
BinaryOperator< T>累加器)

在你的情况下,T是String,所以 BinaryOperator< T> 应该接受两个String参数并返回一个String。但是你传递给它一个int和一个String,这导致你得到的编译错误 - 参数不匹配; int无法转换为java.lang.String 。实际上,我认为传递0作为身份值在这里也是错误的,因为期望一个字符串(T)。



另请注意,此版本的reduce处理流Ts并返回一个T,因此你不能用它来将String流减少为int。



三个参数 reduce 定义为

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

在你的情况下,U是Integer而T是String,所以这个方法会将String流减少为Integer。



对于 BiFunction< U,? super T,U> 累加器你可以传递两种不同类型的参数(U和?super T),在你的情况下是Integer和String。此外,身份值U在你的情况下接受一个整数,所以将它传递0就可以了。



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

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

此处流的类型与 reduce ,所以你可以使用 reduce 的两个参数版本。



当然你没有必须使用 reduce

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


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

For example, the following code doesnt compile :

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

Compile error says : (argument mismatch; int cannot be converted to 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.

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

Can anyone shed light on this?

解决方案

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

The two argument reduce is defined as :

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

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

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.

The three argument reduce is defined as :

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

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

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

Here the type of the stream matches the return type of reduce, so you can use the two parameter version of 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天全站免登陆