[英]What is the best way of filtering by multiple fields in java
我有一個包含 10 個字段的實體:
Class Details{
String item;
String name;
String type;
String origin;
String color;
String quality;
String country;
String quantity;
Boolean availability;
String price;
}
我有一個服務列表的寧靜端點。 我希望用戶能夠為每個字段提供搜索過濾器。 目前我有每個字段的 QueryParam。 然后我使用 java8 流過濾:
List<Detail> details;
details.stream().filter(detail-> detail.getItem()==item).filter(detail-> detail.getName()==name).....collect(Collectors.toList());
如果我有 50 個其他類要過濾多個字段,有沒有辦法概括這一點?
您可以使用.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());
如果你想避免反射,這樣的事情怎么樣?
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());
該方法的主要作用是:
- for each possible query param
- get its value from the request
- if value is present build predicate which
- gets field value from detail object and convert to string
- check that both strings (queried and extracted) matches
- if value is not present return predicate that always returns true
- combine resulting predicates using and
- use always true as fallback (which here never actually happens)
當然,這也可以擴展為根據實際值類型生成謂詞而不是比較字符串,以便例如可以通過“priceMin”和/或“priceMax”請求和處理范圍。
對於 Lambda 詳細信息 -> 條件。 所以我們可以指定需要多少。
details.stream().filter(detail-> detail.getItem()==item && detail.getName()==name && ...)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.