簡體   English   中英

Java 流; 避免在 Collectors.collectingAndThen 上完成終結者

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

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