在Java Lambda流过滤器中外化谓词

时间:2015-05-06 14:13:35

标签: lambda java-8 java-stream

我有一个数据模型的ArrayList,根据用户输入有10个字段,我需要动态地将用户选择字段上的Predicate条件应用于Stream过滤器。

在下面的代码段中应用了一个字段itemDesc,但在运行时用户可以选择任何字段。

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

基本上我们需要动态地而不是预定义地构建谓词,如果是这样的话,任何例子都是可能的。提前谢谢。

1 个答案:

答案 0 :(得分: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()向用户显示选项列表,还可以通过String转换为持久Enum.name()表示,并通过{{1}重构运行时对象可能。

获得所选属性后,使用它进行过滤很容易

DataModelProperty.valueOf(String)