[英]Java Streams; avoid finisher on Collectors.collectingAndThen
我有這個代碼:
private Iterable<Practitioner> pickPractitioners(List<String> ids) {
return Optional.ofNullable(ids)
.map(List::stream)
.orElse(Stream.of())
.collect(
Collectors.collectingAndThen(
Collectors.toList(),
this.practitionerRepository::findAllById
)
);
}
問題是當ids
為空時, this.practitionerRepository::findAllById
也會被執行。
如果結果收集器為空,我想避免這一步。
有任何想法嗎?
通常,要跳過完成器的那部分,您可以傳遞 lambda 而不是方法引用並檢查輸入是否為空:
.collect(
Collectors.collectingAndThen(
Collectors.toList(),
r -> r.isEmpty() ? Collections.emptyList() : this.practitionerRepository.findAllById(r)
)
);
如果您的實際代碼像此示例一樣簡單,那么您根本不需要使用流或可選代碼。 相反,您可以檢查方法的輸入是 null 還是在三元運算符中為空:
return ids == null || ids.isEmpty() ? Collections.emptyList() :
this.practitionerRepository.findAllById(ids);
如果您查看 Finisher 的簽名。 它只是一個 function,所以你可以寫它:
public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher) {
static interface MyRepository extends JpaRepository<Part, Long> {
}
public static void main(String[] args) {
MyRepository myRepository = null;
List<Long> list = null;
Function<List<Long>, List<Part>> finisher = (ids) -> {
return ids.isEmpty() ? Collections.emptyList() : myRepository.findAllById(ids);
};
Optional.ofNullable(list)
.map(List::stream)
.orElse(Stream.of())
.collect(
Collectors.collectingAndThen(
Collectors.toList(),
finisher
)
);
}
雖然這個問題的實際部分( how to avoid interrogating the repository with an empty list as an argument
)已經在其他答案中得到解決,但我想指出,在這種方法中構建管道有一種更簡潔的方法。
首先值得提醒的是, Optional.ofNullable()
的主要目的是創建一個必須returned from a method
的 Optional object 。
根據Stuart Marks ,嘗試使用Optional.ofNullable()
以利用方法鏈接或避免在方法中間進行空檢查被認為是反模式。
以下是他在 Devoxx 演講中的引述:
“為了從其中鏈接方法以獲取值的特定目的而創建 Optional 通常是一個壞主意。”
在他answer on stackoverflow
中表達了類似的想法。
有哪些替代方案?
由於 Java 9 Stream interface
有自己的方法ofNullable()
。
如果非空,則返回包含單個元素的順序 Stream,否則返回空 Stream。
記住所有這些方法pickPractitioners()
可以這樣重寫:
private Function<List<String>, Iterable<Practitioner>> getPractitioners =
idList -> idList.isEmpty() ? Collections.emptyList() :
this.practitionerRepository.findAllById(idList);
private Iterable<Practitioner> pickPractitioners(List<String> ids) {
return Stream.ofNullable(ids)
.flatMap(List::stream)
.collect(Collectors.collectingAndThen(
Collectors.toList(),
getPractitioners
));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.