[英]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.问题是当
ids
为空时, this.practitionerRepository::findAllById
也会被执行。
I'd like to avoid this step if resulting collector is empty.如果结果收集器为空,我想避免这一步。
Any ideas?有任何想法吗?
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:通常,要跳过完成器的那部分,您可以传递 lambda 而不是方法引用并检查输入是否为空:
.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:
相反,您可以检查方法的输入是 null 还是在三元运算符中为空:
return ids == null || ids.isEmpty() ? Collections.emptyList() :
this.practitionerRepository.findAllById(ids);
If you look at the signature of the Finisher.如果您查看 Finisher 的签名。 It is just a function, so you can just write it:
它只是一个 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
)
);
}
Whilst the practical part of this question ( how to avoid interrogating the repository with an empty list as an argument
) is already addressed in other answers I want to point out that there's a cleaner way to build a pipeline in this method.虽然这个问题的实际部分(
how to avoid interrogating the repository with an empty list as an argument
)已经在其他答案中得到解决,但我想指出,在这种方法中构建管道有一种更简洁的方法。
Firstly it's worthy to remind that the main purpose of Optional.ofNullable()
is to create an Optional object that has to be returned from a method
.首先值得提醒的是,
Optional.ofNullable()
的主要目的是创建一个必须returned from a method
的 Optional object 。
Attempts to use Optional.ofNullable()
in order to utilize method-chaining or to avoid null-checks in the middle of the method according to Stuart Marks are considered to be anti-patterns.根据Stuart Marks ,尝试使用
Optional.ofNullable()
以利用方法链接或避免在方法中间进行空检查被认为是反模式。
Here is the quote from his talk at Devoxx :以下是他在 Devoxx 演讲中的引述:
"it's generally a bad idea to create an Optional for the specific purpose of chaining methods from it to get a value."
“为了从其中链接方法以获取值的特定目的而创建 Optional 通常是一个坏主意。”
A similar idea was expressed in his answer on stackoverflow
.在他
answer on stackoverflow
中表达了类似的想法。
What are the alternatives?有哪些替代方案?
Since Java 9 Stream interface
has its own method ofNullable()
.由于 Java 9
Stream interface
有自己的方法ofNullable()
。
Returns a sequential Stream containing a single element, if non-null, otherwise returns an empty Stream.
如果非空,则返回包含单个元素的顺序 Stream,否则返回空 Stream。
Kipping all that in mind method pickPractitioners()
could be rewritten like this:记住所有这些方法
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.