我正試圖一個接一個地運行幾個任務(lambda函式)來轉換一些資料。類似于:
//在建構式中傳遞一些初始資料或者在第一個lambda中生成一些資料。
///執行是一個帶有最終資料的回呼,因為該任務將是異步的。
new MyTask(null).start((d) -> {
return 1.25f;
}).then((f) -> {
return (int)(f*4)。
}).then((i) -> {
return ""/span> i;
}).then((s) -> {
return "The answer is " s;
}).execute((r) -> {
System.out.println(r);
});
我一直在嘗試將我的大腦包裹在完成這樣的事情所需的泛型中,但我認為我對泛型的理解還不夠清晰,不知道這是否或如何能夠實作。
基本來說,我有一個這樣的功能介面:
我有一個這樣的功能介面。
@FunctionalInterface
public interface Middleware<I, O> {
O run(I data)。
}
然后我有一個MyTask類,像這樣:
我有一個MyTask類。
public class MyTask< T> {
private List<Middleware<?, ?>> middlewares = new ArrayList<> ()。
private T data;
public MyTask(T data) {
this.data = data;
}
public <O> MyTask<T> start(Middleware<T, O> middleware) /span> {
middlewares.add(middleware)。
return this。
}
public <I, O> MyTask<T> then(Middleware<I, O> middleware) {
middlewares.add(middleware)。
return this。
}
public void execute(Callback< ?> callback) {
//不知道這里該怎么做,如何用運行中間件和回呼。
//最后的回傳值。
}
}
所以我在呼叫then(...)時,將lambdas存盤在List<middleware>中,但我不知道如何實際運行串列并將資料放進去,然后將結果傳給下一個。我想我需要使用泛型,因為我需要型別被推斷出來,但我有點困惑,似乎不能讓它作業。如果能得到任何幫助,我將不勝感激。我甚至不知道到目前為止我所做的是否是正確的方向。
uj5u.com熱心網友回復:
你在這里所做的基本上是功能組成。
為此,標準的做法是使用Function介面,以及Function. andThen方法(和/或Function.compose,它在當前函式之前應用新函式)。
Function<A, B> function1 = ...
Function<B, C> function2 = ...
Function<A, C> composed = function1.andThen(function2)。
composed將function1應用于輸入,然后取其結果并應用function2。
即使你想嘗試自己實作一個類似的機制,也許值得研究一下Function是如何實作的,以給你一些想法。
實作我認為你想要做的事情的基本要點是,你不希望你的組合方法回傳
this:你實際上只需要 MyTask 來捕獲 output 型別,因為組合和回呼不需要關心初始輸入的型別。
public class MyTask< OutT> {
private final Supplier<OutT> supplier;
private MyTask(Supplier<OutT> supplier) {
this.supplier = supplier。
注意,你實際上不需要將data和middleware分開:你總是使用data作為middleware的輸入,所以你實際上只是提供了一個值:你所需要存盤的只是一個Supplier<OutT>。
現在,讓我們在此添加一些東西。請注意,我把建構式變成了私有的:這是因為我想添加一個工廠方法,這樣你就不能用任何舊的型別來創建一個實體:
public <InT> MyTask<InT> create(InT data) {
return new MyTask<>(()-> data)。
}
這就創建了一個身份實體,將輸入的資料轉換為自己。有點沉悶,但是讓我們從這里開始吧。
對于一個身份轉換,你不再需要一個start方法,因為你已經 "開始 "了。但是讓我們添加一個then:
public <NewOutT> MyTask< NewOutT> then(Middleware<OutT, NewOutT> middleware) {
return new MyTask<>(() -> middleware.run(supplier.get()) )。
}
因此,你傳遞了一個middleware,它可以轉換由供應商提供的值,你將它們組合在一起。
然后你可以有一個執行方法,接受一個回呼,這個回呼需要一個OutT的實體:
public void execute(Callback<OutT> callback) {
callback.accept(supplier.get())。
}
}
(為了清楚起見,上面省略了:你也可以使用通配符來使方法引數更加靈活,例如:Middleware<A, B> middleware -> Middleware<? super A, ? extends B> middleware和Callback< ? super OutT> callback)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/333016.html
標籤:
上一篇:通用制約因素
