[英]Java Generics: chaining together generic function object
我一直在努力解決以下問題。 我有一系列函數對象,每個函數對象都有自己的輸入和輸出類型,通過java中的泛型類型參數定義。 我想在鏈中安排這些,以便將原始數據輸入到第一個函數,轉換為輸出類型,這是下一個對象的輸入類型,依此類推。 當然這對於硬編碼來說是微不足道的,但是我想讓代碼可以插入到新的函數對象中。 如果我只是省略類型參數(只有最終的輸出類型),這就是事情的樣子:
public T process() {
Iterator<Context> it = source.provideData();
for(Pipe pipe : pipeline) {
it = pipe.processIterator(it);
}
return sink.next(it);
}
這里,數據上的迭代器在函數對象之間傳遞,上下文應該是Context。 有沒有辦法保持以下類型的管道可插拔,仍然保持類型安全?
編輯:為了清楚起見,我有一系列功能對象,管道。 每個都將特定類型作為輸入,並輸出另一種類型。 (實際上是這些類型的迭代器)這些將被鏈接在一起,例如, Pipe<A,B> -> Pipe<B,C> -> Pipe<C,D> -> ...
,以便輸出一個pipe是下一個管道的輸入類型。 這里還有一個源,它輸出一個類型為A的迭代器,以及一個接受類型的接收器(過去管道的輸出)。 這會讓事情更清楚嗎? 問題是,因為輸入和輸出類型的兼容性存在嚴重依賴性,有沒有辦法確保這一點?
我開始認為將函數對象插入管道可能是確保類型安全的最佳時間,但我不知道如何做到這一點。
編輯2:我有一個函數對象的加法器方法,如下所示:
public void addPipe(Pipe<?,?> pipe) {
pipeline.add(pipe);
}
我想檢查第一個類型參數是否與當前管道的“結束”相同,如果沒有則拋出異常? 我不認為這里有一個很好的方法來獲得編譯時安全性。 然后可以將當前管道的“結束”設置為輸入管道的第二個類型參數。 我想不出如何用泛型來做這件事,並且傳遞類信息似乎很可怕。
這是一種方法。 run方法不是類型安全的,但考慮到附加管道的唯一方法是以類型安全的方式執行,整個鏈是類型安全的。
public class Chain<S, T> {
private List<Pipe<?, ?>> pipes;
private Chain() {
}
public static <K, L> Chain<K, L> start(Pipe<K, L> pipe) {
Chain<K, L> chain = new Chain<K, L>();
chain.pipes = Collections.<Pipe<?, ?>>singletonList(pipe);;
return chain;
}
public <V> Chain<S, V> append(Pipe<T, V> pipe) {
Chain<S, V> chain = new Chain<S, V>();
chain.pipes = new ArrayList<Pipe<?, ?>>(pipes);
chain.pipes.add(pipe);
return chain;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public T run(S s) {
Object source = s;
Object target = null;
for (Pipe p : pipes) {
target = p.transform(source);
source = target;
}
return (T) target;
}
public static void main(String[] args) {
Pipe<String, Integer> pipe1 = new Pipe<String, Integer>() {
@Override
public Integer transform(String s) {
return Integer.valueOf(s);
}
};
Pipe<Integer, Long> pipe2 = new Pipe<Integer, Long>() {
@Override
public Long transform(Integer s) {
return s.longValue();
}
};
Pipe<Long, BigInteger> pipe3 = new Pipe<Long, BigInteger>() {
@Override
public BigInteger transform(Long s) {
return new BigInteger(s.toString());
}
};
Chain<String, BigInteger> chain = Chain.start(pipe1).append(pipe2).append(pipe3);
BigInteger result = chain.run("12");
System.out.println(result);
}
}
這是另一種方法:這種方式允許轉換步驟以產生列表。 例如,轉換可以將字符串拆分為多個子字符串。 此外,如果轉換任何值產生異常,它允許常見的異常處理代碼。 它還允許使用空List作為返回值,而不是必須進行測試的模糊空值以避免NullPointerException。 這個問題的主要問題是它在進入下一步之前完成了每個轉換步驟,這可能不是內存效率。
public class Chain<IN, MEDIAL, OUT> {
private final Chain<IN, ?, MEDIAL> head;
private final Transformer<MEDIAL, OUT> tail;
public static <I, O> Chain<I, I, O> makeHead(@Nonnull Transformer<I, O> tail) {
return new Chain<>(null, tail);
}
public static <I, M, O> Chain<I, M, O> append(@Nonnull Chain<I, ?, M> head, @Nonnull Transformer<M, O> tail) {
return new Chain<>(head, tail);
}
private Chain(@Nullable Chain<IN, ?, MEDIAL> head, @Nonnull Transformer<MEDIAL, OUT> tail) {
this.head = head;
this.tail = tail;
}
public List<OUT> run(List<IN> input) {
List<OUT> allResults = new ArrayList<>();
List<MEDIAL> headResult;
if (head == null) {
headResult = (List<MEDIAL>) input;
} else {
headResult = head.run(input);
}
for (MEDIAL in : headResult) {
// try/catch here
allResults.addAll(tail.transform(in));
}
return allResults;
}
public static void main(String[] args) {
Transformer<String, Integer> pipe1 = new Transformer<String, Integer>() {
@Override
public List<Integer> transform(String s) {
return Collections.singletonList(Integer.valueOf(s) * 3);
}
};
Transformer<Integer, Long> pipe2 = new Transformer<Integer, Long>() {
@Override
public List<Long> transform(Integer s) {
return Collections.singletonList(s.longValue() * 5);
}
};
Transformer<Long, BigInteger> pipe3 = new Transformer<Long, BigInteger>() {
@Override
public List<BigInteger> transform(Long s) {
return Collections.singletonList(new BigInteger(String.valueOf(s * 7)));
}
};
Chain<String, ?, Integer> chain1 = Chain.makeHead(pipe1);
Chain<String, Integer, Long> chain2 = Chain.append(chain1, pipe2);
Chain<String, Long, BigInteger> chain3 = Chain.append(chain2, pipe3);
List<BigInteger> result = chain3.run(Collections.singletonList("1"));
System.out.println(result);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.