我有一个数据模型的 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/