2015-05-06 66 views
3

我有一個基於用戶輸入的具有10個字段的數據模型的ArrayList,我需要動態地將用戶選擇字段上的謂詞條件應用到Stream過濾器。在Java Lambda流過濾器中將謂詞外化

下面的代碼片段應用於其中一個字段itemDesc,但在運行時用戶可以選擇任何字段。

Predicate<DataModel> contains = (n) -> n.getItemDesc().contains(query);   
List filtered = data.stream().filter(contains).collect(Collectors.toList()); 

基本上我們需要動態地構建謂詞而不是預定義,如果有的話,是否有可能有任何例子。提前致謝。

回答

3

這取決於解決方案的動態程度。對於十個屬性,在編譯時有一個明確的屬性列表而不是動態(反射)發現可能是可以接受的。

可用屬性的聲明可能看起來像

enum DataModelProperty { 
    ITEM_DESC(DataModel::getItemDesc), 
    FOO(DataModel::getFoo), 
    BAR(DataModel::getBar) 
    // the other seven properties… 
    ; 
    final Function<DataModel,String> getter; 

    private DataModelProperty(Function<DataModel, String> f) { 
     getter = f; 
    } 
    public Function<DataModel, String> getPropertyGetter() { 
     return getter; 
    } 
    public Predicate<DataModel> asPredicate(String query) { 
     return n -> getter.apply(n).contains(query); 
    } 
} 

然後你可以使用DataModelProperty.values()通過Enum.name()和運行時的重建,以呈現給用戶的選擇列表,同時也轉換到持久String表示對象通過DataModelProperty.valueOf(String)是可能的。

一旦你選定的屬性,使用它的過濾很容易

DataModelProperty p=DataModelProperty.valueOf("ITEM_DESC");// just as example 

List<DataModel> filtered = data.stream() 
           .filter(p.asPredicate(query)) 
           .collect(Collectors.toList()); 
+0

謝謝你,想你的方法也幫了不少忙。能夠動態構建具有各種屬性和條件的謂詞。乾杯。 – Balaji