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

Externalizing the Predicate in Java Lambda Stream Filter

我有一个数据模型的 ArrayList,它有 10 个基于用户输入的字段我需要将用户 selected 字段上的谓词条件动态应用到流过滤器。

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

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

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

这取决于解决方案的动态程度。对于十个属性,在编译时有一个显式的属性列表而不是动态(反射)发现可能是可以接受的。

可用属性的声明可能类似于

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());