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

标签 lambda java-8 java-stream

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

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

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 转换为持久的 String 表示形式。 name() 并且可以通过 DataModelProperty.valueOf(String) 重构运行时对象。

一旦你有了选择的属性,使用它进行过滤就很容易了

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

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

关于lambda - 在 Java Lambda 流过滤器中外部化谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30079320/

相关文章:

java - 通过使用条件嵌套的列表元素将其与另一个列表匹配来过滤对象

java - 异常原因 java.lang.VerifyError : Bad type on operand stack

arrays - Angular2使用管道基于对象数组过滤对象数组

java - Java 中一个对象与另一个对象的弱关联?

java - 如何使用 Java 8 Lambda 表达式将一种类型的列表转换为其子类型的列表

java - 使用 Collectors.toMap 如何转换 map 值

c# - 是否可以在 lambda 表达式中定位 EventHandler?

c++ - 如何使这些 std::function 参数明确?

java - 可以编译 Java 8 代码以在 Java 7 JVM 上运行吗?

java强制返回类型为通用类型而不是对象类型以使用收集器和流构造映射