2017-05-15 143 views
3

外部配置的過濾可以說,我有一個外部的JSON作爲:使用Java lambda表達式

[{ 
    "condition": "equals", 
    "field": "name", 
    "value": "jack" 
    }, 
    { 
    "condition": "greater", 
    "field": "age", 
    "value": 25 
    } 
] 

這意味着我要檢查,在列表中的用戶對象的人的名字爲"jack"age > 25。 Java 8過濾非常簡單(示例中僅顯示名稱過濾)。

但是,我想使此過濾器可配置並應用多個過濾器。假設下面的人員pojo(這是不言自明的),需要名稱和年齡,我如何使過濾器動態或可配置?

public class Person { 
    private String name; 
    private int age; 

    public Person(String name, int age) { 
     this.name = name; 
     this.age = age; 
    } 

    // Accessors and Mutators 
} 
List<Person> persons = Arrays.asList(
    new Person("mkyong", 30), 
    new Person("jack", 20), 
    new Person("lawrence", 40) 
); 

Person result1 = persons.stream()   // Convert to steam 
    .filter(x -> "jack".equals(x.getName())) // we want "jack" only 
    .findAny()        // If 'findAny' then return found 
    .orElse(null); 

我期待着滿足的標準,結果Person對象的列表。

回答

5

據我所知,這與streams本身沒有多大關係。該過濾方法只是一個Predicate,它可以作爲實例提供,例如可以從您可以創建的工廠方法中提供。

static Predicate<Person> fromName(String value){ 
    return p -> p.getName().equals(value); 
} 

假設你有另一種方法:

static Predicate<Person> fromAge(int value) { 
    return p -> p.getAge() == value; 
} 

因爲Predicate.andPredicate.or存在,你可以這樣做:

fromAge(12).and(fromName("jack")); 

從而鏈謂詞

2

有兩種方法可供選擇。

要麼你只是連鎖調用所需的過濾器內聯:

Person result1 = persons.stream() 
    .filter(x -> "jack".equals(x.getName())) 
    .filter(x -> 25 > x.getAge()) // new filter 
    .findAny() 
    .orElse(null); 

或者,你有你自己的類實現Predicate<Person>

在這種情況下,您可以使用構建器模式逐步構建謂詞。是

你必須要面對的困難如下:

  • 處理布爾術語之間(&& VS ||
  • (a && b) || c不是a && (b || c))關係處理嵌套布爾關係

請注意Predicate有方便的andor方法鏈式謂詞。