我目前正在尝试使用Java 8的Future API和Core CompleteableFuture。我知道它是一个monad,所以它应该有一个bind-Operator。
现在的想法是我有一个抽象操作k树,例如像这样:
O --- > O3 ---> O4 ---> o5
O ---> o2 --/
我想将O3
和O2
“合并”到新的操作O4 = (O3 o O2) (t) = O2(O3(t))
中。
我的想法是,我是在O2
中,并想说:将当前节点与O3
合并,并返回由连接操作组成的新节点。
不幸的是,我已经尝试了一整夜,我无法弄明白。
此外,由于未知原因,使用像O1.mergeWith(O2).mergeWith(O3)
之类的运算符会触发apply方法两次以进行单调调用。
目标是创建一个由其他函数组成的新函数,这样我就可以尽可能地推迟计算。
public abstract class Operation<T,R> {
// The value a
private final CompletableFuture<R> future;
// Executes the operation on t and returns something (maybe different) of type R
protected abstract R apply(T t);
// Gets the value of the future of this operation
public R get() throws Exception {
return future.get();
}
protected Operation(Supplier<T> s) {
future = CompletableFuture.supplyAsync(s).thenApplyAsync(transform());
}
protected Operation(CompletableFuture<R> f) {
future = f;
}
CompletableFuture<R> createTargetFuture(R _value) {
return CompletableFuture.supplyAsync(() -> _value);
}
<S> Operation<T,S> mergeWith(Operation<R,S> _other) {
CompletableFuture<S> _result = future.thenComposeAsync(
// Method is synchronous, but is run async :) We need the createTargetFuture, otherwise we cannot turn the constant t into a producer.
(t) -> _other.createTargetFuture(_other.apply(t)));
//transform()).thenApplyAsync(_other.transform());
return new Operation<T, S>(_result) {
@Override
protected S apply(T t) {
// What to put here
return null;
}
};
}
protected Function<T,R> transform(){
return this::apply;
}
}
答案 0 :(得分:2)
你想要实现的目标并不是很清楚。您的整个Operation
课程似乎都在为CompletableFuture
添加一个已经提供的功能。
如果您有Supplier<T> s
并希望推迟执行,则可以按照您已知的方式CompletableFuture.supplyAsync(s)
进行操作。
现在,如果您要将Function<T,R> f
应用于CompletableFuture<T> a
的推迟结果,只需使用CompletableFuture.supplyAsync(()->f.apply(a.join()))
。
同样适用于两个CompletableFuture
和一个BiFunction
:CompletableFuture.supplyAsync(()->f.apply(a.join(),b.join()))
如果您需要将操作包装在某种支持代码中,可以创建如下的实用程序方法:
public static <T> CompletableFuture<T> create(Supplier<T> s) {
return CompletableFuture.supplyAsync(s);
}
public static <T,R> CompletableFuture<R> create(
Function<T,R> f, CompletableFuture<T> a) {
return CompletableFuture.supplyAsync(()->f.apply(a.join()));
}
public static <T,U,R> CompletableFuture<R> create(
BiFunction<T,U,R> f, CompletableFuture<T> a, CompletableFuture<U> b) {
return CompletableFuture.supplyAsync(()->f.apply(a.join(),b.join()));
}
然后您可以愉快地执行异步操作,例如:
int i=create((a,b)->a+b, create(()->42),create(()->100)).join();
但是,当然,同样的事情也可以在没有任何支持方法的情况下发挥作用:
int i=CompletableFuture.supplyAsync(() ->
CompletableFuture.supplyAsync(()->42).join()
+ CompletableFuture.supplyAsync(()->100).join() ).join();
或
int j=CompletableFuture.supplyAsync(()->42).thenApplyAsync(
a-> a + CompletableFuture.supplyAsync(()->100).join() ).join();