gpt4 book ai didi

java - 在 Java 8 中使用先前链接的 thenCompose lambda 的值

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:19:52 25 4
gpt4 key购买 nike

我的同事喜欢的 Java 8 编码风格是一直链接异步调用,例如

CompletionStage<E> someMethod() {
return doSomething().thenCompose(a -> {
// ...
return b;
}).thenCompose(b -> {
// ...
return c;
}).thenCompose(c -> {
// ...
return d;
}).thenApply(d -> {
// ...
return e;
});
}

我有类似上面的内容,但还有一个额外的挑战:我需要在后面的 lambda 中记忆在一些 lambda 中检索到的值。例如,

CompletionStage<E> someMethod() {
return doSomething().thenCompose(a -> {
// ...
Foo foo = fooDAO.getFoos(a);
// ...
return b;
}).thenCompose(b -> {
// ...
return c;
}).thenCompose(c -> {
// ...
Bar bar = barDAO.getBars(foo);
// ...
return d;
}).thenApply(d -> {
// ...
return someResult(d, bar);
});
}

当我在外部范围内声明 Foo foo;Bar bar; 时,我收到关于它们不是最终的或实际上不是最终的错误。我读到了有关使用包装器使它们有效地最终化的信息,但是这样做对我来说似乎很老套(我不明白为什么允许这样做...)

我读到 Java 8 没有添加对元组的支持(虽然它考虑了 BiVal,也许我可以用来传递给 BiFunction lambda)。所以我尝试使用配对,例如

    return doSomething().thenCompose(a -> {
// ...
Foo foo = fooDAO.getFoos(a);
// ...
return new Pair<>(foo, b);
}).thenCompose(fooAndB -> {

然后在任何我需要调用foo的地方,

      Foo foo = fooAndB.getKey();

但这感觉在语义上是错误的。而且,它不起作用!我不知道为什么,因为我认为 lambda 参数的范围与其外部范围相同,因此所有 lambda 参数都可以从稍后链接的 lambda 中访问。

lambda 参数的真正范围是什么,是否有一种惯用的或至少在语义上无害的方式来做我想做的事情,同时保持链接?

基于打破链条的答案很好,因为它们可能对 future 的观众有用,但就我而言,偏离此 repo 协议(protocol)中的主导风格可能会导致 PR 对话和批准延迟,所以我喜欢保留链接的解决方案。或者,解释或演示试图保持链接是多么疯狂。谢谢!

最佳答案

由于您提到了同事喜欢的编码风格,您可能已经知道使用嵌套调用的替代方法:

CompletionStage<E> someMethod() {
return doSomething().thenCompose(a -> {
// ...
Foo foo = fooDAO.getFoos(a);
// ...
CompletableFuture<B> resultB = ...;
return resultB.thenCompose(b -> {
// ...
CompletableFuture<C> resultC = ...;
return resultC;
}).thenCompose(c -> {
// ...
Bar bar = barDAO.getBars(foo);
// ...
CompletableFuture<D> resultD = ...;
return resultD.thenApply(d -> {
// ...
return someResult(d, bar);
});
});
});
}

这会立即解决您的问题,但代价是代码的可读性稍差一些。但是这个问题可以通过从您的代码中提取一些方法来轻松解决:

CompletionStage<E> someMethod() {
return doSomething()
.thenCompose(this::processA);
}

private CompletionStage<E> processA(final A a) {
// ...
Foo foo = fooDAO.getFoos(a);
// ...
final CompletableFuture<B> result = ...;
return result
.thenCompose(this::processB)
.thenCompose(c -> processCAndFoo(c, foo));
}

private CompletionStage<C> processB(B b) {
// ...
return ...;
}

private CompletionStage<E> processCAndFoo(final C c, final Foo foo) {
// ...
Bar bar = barDAO.getBars(foo);
// ...
final CompletableFuture<D> result = ...;
return result
.thenApply(d -> someResult(d, bar));
}

通过这样做,您可以避免嵌套的 lambda(并尊重您同事的首选代码风格),但您也可以获得可读性和可测试性,因为您现在有几个更容易理解和单元测试的小方法。

关于java - 在 Java 8 中使用先前链接的 thenCompose lambda 的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52669585/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com