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的签名。它只是一个函数,所以你可以这样写:

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() 的主要目的是创建一个 Optional 对象,它必须是 returned from a method.

尝试使用Optional.ofNullable()以利用method-chaining或根据Stuart Marks在方法中间避免null-checks被认为是anti-patterns.

引用他的 talk at Devoxx:

"it's generally a bad idea to create an Optional for the specific purpose of chaining methods from it to get a value."

他的 .

中表达了类似的想法

有哪些选择?

因为Java9Stream interface有自己的方法ofNullable().

Returns a sequential Stream containing a single element, if non-null, otherwise returns an empty 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
            ));
}