在java中按多个字段过滤的最佳方法是什么?

时间:2017-03-08 18:37:01

标签: java java-8 java-stream

我有一个包含10个字段的实体:

Class Details{
  String item; 
  String name; 
  String type;
  String origin; 
  String color; 
  String quality;
  String country;
  String quantity;
  Boolean availability;
  String price;
 }

我有一个为List提供服务的restful端点。我希望用户能够为每个字段提供搜索过滤器。 目前我有每个字段的QueryParam。然后我使用java8 stream过滤:

List<Detail> details;
details.stream().filter(detail-> detail.getItem()==item).filter(detail-> detail.getName()==name).....collect(Collectors.toList());

如果我有其他50个我想要过滤的多个字段的类,有没有办法概括这个?

3 个答案:

答案 0 :(得分:3)

您可以使用.and().or()编写此类谓词,从而允许您定义应用所有检查的单个聚合谓词,而不是尝试链接 n .filter()来电。这样就可以在运行时构建任意复杂的谓词。

// Note that you shouldn't normally use == on objects
Predicate<Detail> itemPredicate = d-> item.equals(d.getItem());
Predicate<Detail> namePredicate = d-> name.equals(d.getName());

details.stream()
    .filter(itemPredicate.and(namePredicate))
    .collect(Collectors.toList());

答案 1 :(得分:1)

如果你想避免反思这样的事情呢?

observe

然后,假设您可以通过例如访问查询参数static enum DetailQueryParams { ITEM("item", d -> d.item), NAME("name", d -> d.name), TYPE("type", d -> d.type), ORIGIN("origin", d -> d.origin), COLOR("color", d -> d.color), QUALITY("quality", d -> d.quality), COUNTRY("country", d -> d.country), QUANTITY("quantity", d -> d.quantity), AVAILABILITY("availability", d -> d.availability), PRICE("price", d -> d.price); private String name; private Function<Detail, Object> valueExtractor; private DetailQueryParams(String name, Function<Detail, Object> valueExtractor) { this.name = name; this.valueExtractor = valueExtractor; } public static Predicate<Detail> mustMatchDetailValues( Function<String, Optional<String>> queryParamGetter) { return Arrays.asList(values()).stream() .map(p -> queryParamGetter.apply(p.name) .map(q -> (Predicate<Detail>) d -> String.valueOf(p.valueExtractor.apply(d)).equals(q)) .orElse(d -> true)) .reduce(Predicate::and) .orElse(d -> true); } } 返回request.getQueryParam(String name)值或String,请通过调用以下代码来使用该代码:

null

该方法基本上是:

details.stream()
    .filter(DetailQueryParams.mustMatchDetailValues(
            name -> Optional.ofNullable(request.getQueryParam(name))))
    .collect(Collectors.toList());

当然,这也可以扩展为根据实际值类型生成谓词,而不是比较字符串,以便例如可以通过&#34; priceMin&#34;来请求和处理范围。和/或&#34; priceMax&#34;。

答案 2 :(得分:0)

对于 Lambda 详细信息 -> 条件。所以我们可以指定需要多少。

method_missing