Java reduce on stream on mutable object



在阅读https://stackoverflow.com/a/38728166/7826451后,OP说减少操作应该在不可变对象上完成,下面的用法是错误的,如果是为什么?它产生的结果是我所期望的'foo'对象中的第4个。

@Test
public void foo() {
List<Foo> foos = new ArrayList<>();
foos.add(new Foo(1));
foos.add(new Foo(1));
foos.add(new Foo(1));
foos.add(new Foo(1));
Foo foo = foos.stream().reduce(new Foo(0), Foo::merge);
System.out.println();
}
static class Foo {
int foo;
Foo(int f) {
foo = f;
}
Foo merge(Foo other) {
foo += other.foo;
return this;
}
}

考虑以下内容。Integer是不可变的,Foo是可变的。创建两个列表

List<Foo> foos = IntStream.range(1, 1001).mapToObj(Foo::new)
.collect(Collectors.toList());
List<Integer> ints = IntStream.range(1,1001).boxed()
.collect(Collectors.toList());

现在将每个流简化为单个结果。

Foo foo = foos.stream().reduce(new Foo(0), Foo::merge);
Integer intVal = ints.stream().reduce(Integer.valueOf(0), (a,b)->a+b);
System.out.println(foo);
System.out.println(integer);

打印

500500
500500

都是正确的

现在通过并行流再次使用线程来减少它们,使用第三个参数组合不同的线程来减少。

Foo foo = foos.parallelStream().reduce(new Foo(0), Foo::merge, Foo::merge);
Integer integer = ints.parallelStream().reduce(Integer.valueOf(0), (a,b)->a+b, (a,b)->a+b);
System.out.println(foo);
System.out.println(integer);

打印

570026
500500

哦!这个问题与多个线程和foo对象同时更新而没有任何适当的同步有关。

如果您将Foo类合并方法修改如下,则一切正常。

Foo merge(Foo other) {
return new Foo(this.foo + other.foo);
}

所以Foo仍然可以通过setter来改变,但是你不应该在约简操作中使用这些。总是返回一个新实例,而不是修改当前实例。


class Foo {
int foo;

Foo(int f) {
foo = f;
}

Foo merge(Foo other) {
foo+=other.foo;
return new Foo(foo);
}
public String toString() {
return foo + "";
}
}
}

相关内容

最新更新