簡體   English   中英

在java中按多個字段過濾的最佳方法是什么

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM