2017-05-15 148 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方法链式谓词。