有没有办法用Java 8流和lambdas表达以下代码?
ImmutableObject immutable = new ImmutableObject();
for(int i = 0; i < 10; i++) {
immutable = immutable.changeState(i);
}
return immutable;
ImmutableObject只是一个简单的不可变对象:
class ImmutableObject {
private final int state;
public ImmutableObject() {
this(0);
}
public ImmutableObject(final int state) {
this.state = state;
}
public ImmutableObject changeState(final int newState) {
return new ImmutableObject(newState);
}
}
我想出了这个:
IntStream.range(0, 10).
mapToObj(i -> immutable.changeState(i)).reduce((a, b) -> b).get()
但是每次迭代的结果都被丢弃 - 我不能将结果分配回不可变引用,因为它在lamba表达式中并且应该(有效地)为final。
答案 0 :(得分:1)
这是溪流不能解决所有事情的完美例子。
但是,如果您坚持,这里是一个流版本,在“holder”对象上使用collect()
,因此可以更新参考值。
这是一个黑客,它很难看,但它会起作用。
为了使它成为MCVE,我创建了一个简单的不可变和实现。
public class Test {
public static void main(String[] args) {
ImmutableObject o = IntStream.range(0, 10).collect(
() -> new ImmutableObject[] { new ImmutableObject(0) },
(h, i) -> h[0] = h[0].changeState(i),
(h1, h2) -> { throw new UnsupportedOperationException("Parallel not supported"); }
)[0];
System.out.println(o); // prints: 45
}
}
class ImmutableObject {
private final int v;
ImmutableObject(int v) { this.v = v; }
ImmutableObject changeState(int i) { return new ImmutableObject(this.v + i); }
@Override public String toString() { return Integer.toString(this.v); }
}
答案 1 :(得分:1)
让我们一步一步来做。首先用流替换循环。
private static Immutable immutable = new Immutable(0);
public static void main(String[] args) {
IntStream.range(0,10).forEach(i -> {
Immutable localImmutable = immutable.changeState(i);
System.out.println(localImmutable.toString());
});
}
它在1..10中为i执行,因为range()具有独占上限。
接下来,您希望存储引用新的Immutable实例(代码中的ImmutableObject)。您可以在lambda(或更广泛意义上的任何Java闭包)中访问最终(或有效最终)变量。也许您已经听说过每个lambda(或闭包)都引用了它的上下文。我们可以使用此上下文来访问静态字段。我们来试试吧
private static Immutable immutable = new Immutable(0);
public static void main(String[] args) {
IntStream.range(0,10).forEach(i -> {
immutable = immutable.changeState(i);
System.out.println(immutable.toString());
});
}
由于上下文无法改变其有效的最终结果(在某些语言中 - 如groovy - 您可以通过设置适当的委托来选择不同的上下文)。最后但并非最不重要的是让我们摆脱静态关键字。我结束了示例
import java.util.stream.IntStream;
public class Test {
private static class Immutable {
private static int counter = 0;
private final int id = ++counter;
private final int state;
public Immutable(int state) {
this.state = state;
}
public Immutable changeState(int i) {
return new Immutable(i);
}
@Override
public String toString() {
return "id: " + id + ", state: " + state;
}
}
private Immutable immutable = new Immutable(0);
public void run() {
IntStream.range(0,10).forEach(i -> {
immutable = immutable.changeState(i);
System.out.println(immutable.toString());
});
}
public static void main(String[] args) {
new Test().run();
}
}
如果你想松开私人领域,你可以使用
public static void main(String[] args) {
Optional<Immutable> last = IntStream.range(0,10).boxed()
.map(Immutable::new)
.reduce((a,b) -> b);
System.out.println(last.get());
}