如果你想避免反思這樣的事情呢?
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」來請求和處理。
這可能是反射可能派上用場的罕見情況之一:所以不要像在你的例子中那樣手動寫下所有的屬性,你可以用反射來「按名稱」。但我想知道有多少設計進入了一個模型,導致50個班級看起來像這樣。 – GhostCat
不要將字符串與'=='進行比較。使用equals方法或使用[Objects.equals](http://docs.oracle.com/javase/8/docs/api/java/util/Objects.html#equals-java.lang.Object-java。 lang.Object-)。請參閱http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java。 – VGR