我试图了解该reduce()方法如何在java-8中工作。
例如,我有以下代码:
public class App {
public static void main(String[] args) {
String[] arr = {"lorem", "ipsum", "sit", "amet"};
List<String> strs = Arrays.asList(arr);
int ijk = strs.stream().reduce(0,
(a, b) -> {
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
},
(a, b) -> {
System.out.println("Combiner");
return a * b;
});
System.out.println(ijk);
}
}
Run Code Online (Sandbox Code Playgroud)
输出是这样的:
Accumulator, a = 0, b = lorem
Accumulator, a = 5, b = …Run Code Online (Sandbox Code Playgroud) 当reduce()在并行流上使用该操作时,OCP考试书指出reduce()参数必须遵守某些原则.这些论点如下:
(a op b) op c等于a op (b op c).u和t combiner.apply(u, accumulator.apply(identity, t))等于accumulator.apply(u,t).考试书提供了两个例子来说明这些原则,请参阅下面的代码:
关联的示例:
System.out.println(Arrays,asList(1,2,3,4,5,6))
.parallelStream()
.reduce(0,(a,b) -> (a-b))); //NOT AN ASSOCIATIVE ACCUMULATOR
Run Code Online (Sandbox Code Playgroud)
OCP书中对此有何说法:
它可能会输出-21,3或其他一些值,因为累加器函数违反了associativity属性.
身份要求的示例:
System.out.println(Arrays.asList("w","o","l","f"))
.parallelStream()
.reduce("X", String::concat));
Run Code Online (Sandbox Code Playgroud)
OCP书中对此有何说法:
如果我们使用的身份参数不是真正的身份值,您可以看到其他问题.它可以输出XwXoXlXf.作为并行过程的一部分,标识将应用于流中的多个元素,从而导致非常意外的数据.
我不明白这些例子.使用累加器示例,累加器以0 -1 = -1然后-1 -2开始,其中= -3然后-6等等一直到-21.我明白,因为生成的arraylist不同步,结果可能是不可预测的,因为竞争条件等的可能性,但为什么累加器不关联?Woulden也不会(a+b)导致不可预测的结果?我真的没有看到示例中使用的累加器有什么问题,以及为什么它不是关联的,但是我仍然不能完全理解关联原则是什么.
我也不了解身份的例子.据我所知,如果4个独立的线程同时开始与身份一起累积,那么结果确实可能是XwXoXlXf,但这与身份参数本身有什么关系呢?究竟什么是适当的身份才能使用呢?
我想知道是否有人可以更多地了解这些原则.
谢谢
我写了这个通用谓词:
private static <T> Predicate<T> isNull(){
return Objects::isNull;
}
Run Code Online (Sandbox Code Playgroud)
但是我不能将它与其他这样的谓词结合使用:
private static Predicate<String> isEmpty(){
return string -> string.isEmpty();
}
Run Code Online (Sandbox Code Playgroud)
因为这个片段不会编译(期望 Predicate<String> in or operation):
isNull().or(isEmpty())
Run Code Online (Sandbox Code Playgroud)
有什么想法可以解决吗?谢谢!
我想将列表中的所有元素相乘,然后使用Java 8中的流将该结果乘以5.这是我的代码:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int mul = numbers.stream().reduce(5, (acc, x) -> x * acc);
System.out.println(mul);
Run Code Online (Sandbox Code Playgroud)
这给了我正确的结果,120.但是如果我们改变它parallelStream()然后它会产生错误的值.为什么?在这种情况下,为什么并行化会产生错误的结果?什么是修复?
我真的想知道两者之间的确切区别 Stream.reduce() and Stream.parallel.reduce()
要清除所有内容,我创建了一个小程序,发现结果不等于相同的值.
public class Test {
public static void main(String[] args) {
int a = Stream.of(1, 2, 3).map(i -> i * 10).reduce(5, (abc, cde) -> abc + cde);
int b = Stream.of(1, 2, 3).map(i -> i * 10).
parallel().reduce(5, (abc, cde) -> abc + cde);
System.out.println(a == b) //False;
}
}
Run Code Online (Sandbox Code Playgroud)
那么,这是否意味着它们两者都是不同的,请帮助我理解它们在功能方面有何不同?
并行运行时 a==b 为何为 false 但与组合器一起使用时却有效?
public class test {
public static int cal(final int i) {
return 1;
}
public static void main(String args[]) {
int a = IntStream.range(0, 3).reduce(0, (abc, cde) -> abc + cal(cde));
int b = IntStream.range(0, 3).parallel().reduce(0, (abc, cde) -> abc + cal(cde));
System.out.println(a == b); // false
int c = List.of(0, 1, 2).stream().parallel().reduce(0, (abc, cde) -> abc + cal(cde), Integer::sum);
System.out.println(a == c); // true
}
}
Run Code Online (Sandbox Code Playgroud)