0

我是一個數據挖掘工具,因此我花費大量時間以各種方式轉換原始數據,以便通過預測模型進行消耗。例如,以特定格式讀取文件,標記,克隆,並投影到某種數字表示形式。多年來,我開發了一套豐富的方法來完成大部分我能想到的數據處理任務,但我沒有一種很好的方式來配置這些組件,除了最基本的方式 - 通常我所做的是很多對源代碼中依賴於特定任務的特定方法的調用。我現在試圖將我的圖書館重構成更好的東西,但我不太確定這是什麼。我現在的想法是,有一個函數對象列表,每個函數對象都定義了一些方法(比如說操作(...)),它們按順序調用,每個方法都是通過引用來處理某些數據流的內容,或者消耗前一個函數對象的輸出。這與我想要的接近,但因爲輸入和輸出的數據類型會有所不同,所以使用泛型變得非常困難。用我上面的例子中,我想通過處理類似數據這一「管道」傳遞的東西:Java模式:用於數據挖掘任務的工程數據流

input: string filename 
filename -> collection of strings 
collection<string> -> (stemming, stopword removal) -> collection of strings 
collection<string> -> (tokenize) -> collection of string arrays 
collection<string[]> -> (gram-ify) -> augment individual token strings with n-grams -> collection of string arrays 
collection<string[]> -> projection into numeric vectors -> collection<double[]> 

這是一個簡單的例子,但是想象一下,我有這樣的組件的100S,我想將它們添加到某些數據流中。這符合我容易配置的要求 - 我可以輕鬆構建一個讀取一些yaml文件並構建出來的管道工廠。然而,組件的設計模式一直困擾着我一段時間?適當的界面是什麼樣的?看起來在這裏做事情的唯一簡單方法是讓對象得到傳遞,實質上取消對象(或者讓一些上下文對象通過,將對象作爲成員變量傳遞),然後檢查輸入的兼容性,拋出運行時異常。這兩種選擇似乎同樣糟糕。不過,我覺得我已經接近了一個非常好的靈活系統。你們能幫我把它推過籬笆嗎?

回答

1

Apache基金會有一個項目叫管道https://commons.apache.org/sandbox/pipeline/。也許它可以是有用的。我認爲那裏有更多的管道項目。瀏覽該網站可能很有用。

+0

看起來很近!然而這個罐子目前似乎無法使用...... – downer

+0

你可以下載源代碼,看起來像一個項目maven文件。你可以自己將它編譯成jar。你也可以看看接口的設計,以瞭解他們在做什麼。此外,還有另一個名爲Cocoon的Apache項目也使用管道方法。你可能想看看:http://cocoon.apache.org/ –

1

我認爲一個更靈活的工具將你的圖書館結合在一起將是一個很好的方法。例如其中一種新的動態語言對此非常有用。

Clojure將非常適合所有內置的工具,如map,pmap,reduce filter等.Clojure的集合全部實現java.util集合庫的接口,因此您可以將更高級別的Clojure函數應用於現有的Java代碼,或者您也可以將Clojure數據結構直接傳遞給您的Java代碼(只要Java代碼不希望修改它)。

該語言的輕量級和動態特性可以很容易地將事物整合在一起,而不會產生太多的開銷。

+0

儘管學習一種新語言可能有點多,不是嗎? – downer

+0

這真的取決於你。它並不難開始,尤其是如果您將它用作膠水語言的話。你已經有了可行的東西。所以,如果你花一些時間開始學習Clojure,並開始找到應用它的小方法,你將會受益。如果你決定不喜歡它,那麼你可以繼續前進。 – Bill

1

我可能會逐字閱讀你的例子;這意味着此解決方案可能不適用於您的真實問題。

public interface Interface1 { 
    public List<String> operate(List<String> list); 
} 

public interface InterfaceBridge { 
    public List<List<String>> operate(List<String> list); 
} 

public interface Interface2 { 
    public List<List<String>> operate(List<List<String>> list); 
} 

你應該明顯地選擇更好的接口名稱。然後你可以把它們組合起來:

public class Interface1Composite implements Interface1 { 
    List<Interface1> components = new ArrayList<>(); 

    public Interface1Composite(Interface1... components) { 
    for (Interface1 i1 : components) 
     this.components.add(i1); 
    } 

    @Override 
    public List<String> operate(List<String> list) { 
    for (Interface1 i1 : components) 
     list = i1.operate(list); 
    return list; 
    } 

我想這幾乎是你已經做的。我只是簡化了3種類型的接口,而不是嘗試使用泛型。但正如我剛纔所說,我不知道你是否可以將它應用於你的問題。

+0

這樣可以用於字符串示例,但是對於任意數據類型呢?特別是混合類型?一些標識符到數據結構本身的映射?另外,我最初並沒有明確說明這一點 - 有時我想通過單個示例(例如,當用作處理個別請求的某些Web服務中的組件時)和其他時間,集合在某些批處理模式下使用時。一個項目清單是好的,但有點難看我會說。限制性更強 - 某些組件要求所有相關數據在處理和傳遞輸出之前都存在,其他組件不具備此限制。 – downer