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
));
}
我有这个代码:
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
));
}