collect()
方法是可变的。基于Java文档:
可变归约运算在处理流中的元素时将输入元素累积到可变结果容器(例如Collection或StringBuilder)中。
我尝试了以下内容,并且编译没有问题。
Stream<String> stream1 = Stream.of("w", "o", "l", "f");
String word = stream1.collect(String::new, String::concat, String::concat);
System.out.println(word);
如果供应商是StringBuffer,则我将查看collect操作,因为元素将附加到提供的StringBuffer上。
由于String是不可变的对象,可变约简在这里如何工作?会与每次执行累加器时创建新对象的reduce操作一样吗?
答案 0 :(得分:4)
由于String是不可变的对象,因此可变约简在这里如何工作?
不是。运行该命令时,将得到一个空字符串(Supplier only
的结果)。编译器无法强制检查Supplier是否返回一个不可变的对象,这绝对是它不能执行的操作。而且由于您的容器是不可变的,因此只需忽略对其的更新。就像这样做:
String s = "abc";
s.concat("def"); // the result is ignored here
如果您将其写为lambda,可能会更有意义:
Stream<String> stream1 = Stream.of("w", "o", "l", "f");
String word = stream1.collect(
String::new,
(left, right) -> {
left.concat(right); // result is ignored
},
String::concat);
另一方面,当您使用reduce时,会强制返回某些内容:
String word = stream1.reduce(
"",
(x, y) -> {
return x.concat(y);
},
(x, y) -> {
return x.concat(y);
});
当然,您仍然可以这样做:
String word = stream1.reduce(
"",
(x, y) -> {
x.concat(y);
return x; // kind of stupid, but you could
},
(x, y) -> {
return x.concat(y);
});
如果您想破坏它;但这不是重点。
答案 1 :(得分:1)
根据Oracle / Java文档:
收集
<R> R collect(Supplier<R> supplier, <R,? super T> accumulator, <R,R> combiner)
对此流的元素执行可变的归约运算。可变归约法是将归约值作为一个可变结果容器(例如ArrayList),并且通过更新结果的状态而不是通过替换结果来合并元素的方法。
可变削减
可变归约运算在处理流中的元素时将输入元素累积到可变结果容器(例如Collection或StringBuilder)中。 如果我们想获取字符串流并将其连接为单个长字符串,则可以通过普通归约来实现:
串联的字符串= strings.reduce(“”,String :: concat)
因此,总而言之,它之所以有效,是因为Java在后台使用了stringbuilder