'Java Streams; avoid finisher on Collectors.collectingAndThen

I've this code:


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
            )
        );

}

Problem is that when ids is empty, this.practitionerRepository::findAllById is also executed.

I'd like to avoid this step if resulting collector is empty.

Any ideas?



Solution 1:[1]

In general to skip that part of the finisher you could pass a lambda instead of a method reference and check if the input is empty:

    .collect(
        Collectors.collectingAndThen(
            Collectors.toList(),
            r -> r.isEmpty() ? Collections.emptyList() : this.practitionerRepository.findAllById(r)
        )
    );

If your actual code is a simple as this example then you don't need to use streams or optional at all. Instead you could just check if the input of the method is null or empty in a ternary operator:

    return ids == null || ids.isEmpty() ? Collections.emptyList() :
        this.practitionerRepository.findAllById(ids);

Solution 2:[2]

If you look at the signature of the Finisher. It is just a function, so you can just write it:

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
                    )
            );

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 JCompetence