【发布时间】:2020-01-22 04:16:22
【问题描述】:
我一直被告知不通过诸如 collect 和 findFirst 之类的方法终止 Stream 是不好的做法,但对于为什么在博客中没有太多谈论它没有真正的反馈。
看下面的例子,我没有使用大量的嵌套 if 检查,而是使用 Optional 来取回一个 List 值。如您所见,我的最后一步是在该 Stream 中进行过滤。这对我来说按预期工作,即取回一个列表。为什么这是错误的,我应该怎么写呢?
import lombok.Getter;
import lombok.Setter;
import java.util.*;
public class Main {
public static void main(String[] args) {
RequestBean requestBean = new RequestBean();
// if I uncomment this I will get the list values printed as expected
// FruitBean fruitBean = new FruitBean();
// AnotherBean anotherBean = new AnotherBean();
// InnerBean innerBean = new InnerBean();
// requestBean.setFruitBeans(Collections.singletonList(fruitBean));
// fruitBean.setAnotherBeans(Collections.singletonList(anotherBean));
// anotherBean.setInnerBeans(Collections.singletonList(innerBean));
// List<String> beans = Arrays.asList("apple", "orange");
// innerBean.setBeans(beans);
List<String> result = getBeanViaOptional(requestBean);
if(result != null){
for(String s : result){
System.out.println(s);
}
}else {
System.out.println("nothing in list");
}
}
private static List<String> getBeanViaOptional(RequestBean bean){
Optional<List<String>> output = Optional.ofNullable(bean)
.map(RequestBean::getFruitBeans)
.map(n -> n.get(0))
.map(FruitBean::getAnotherBeans)
.map(n -> n.get(0))
.map(AnotherBean::getInnerBeans)
.map(n -> n.get(0))
.map(InnerBean::getBeans)
// why is this bad practice to end with a filter. how should I write this then?
.filter(n -> n.contains("apple"));
if(!output.isPresent()){
throw new CustomException();
}
return output.get();
}
// not using this. just to show that optional was preferable compared to this.
private static List<String> getBeanViaIfChecks(RequestBean bean){
if(bean != null){
if(bean.getFruitBeans() != null){
if(bean.getFruitBeans().get(0) != null){
if(bean.getFruitBeans().get(0).getAnotherBeans() != null){
if(bean.getFruitBeans().get(0).getAnotherBeans().get(0) != null){
if(bean.getFruitBeans().get(0).getAnotherBeans().get(0).getInnerBeans() != null){
if(bean.getFruitBeans().get(0).getAnotherBeans().get(0).getInnerBeans().get(0) != null){
return bean.getFruitBeans().get(0).getAnotherBeans().get(0).getInnerBeans().get(0).getBeans();
}
}
}
}
}
}
}
return null;
}
}
@Getter
@Setter
class RequestBean{
List<FruitBean> fruitBeans;
}
@Getter
@Setter
class FruitBean{
List<AnotherBean> anotherBeans;
}
@Getter
@Setter
class AnotherBean{
List<InnerBean> innerBeans;
}
@Getter
@Setter
class InnerBean{
List<String> beans;
}
class CustomException extends RuntimeException{
// do some custom exception stuff
}
【问题讨论】:
-
但是这个
filter方法来自Optional而不是Stream。 -
我不知道为什么/何时会出现
get(0)的此类用例,虽然我不确定是否有更清洁的方法来避免它们。在阅读功能性方法时,它们确实让我的眼睛发痒。 -
这两种方法之间需要注意的另一点是,传统的
for循环方法不等同于函数方法,因为它不会抛出CustomException。 -
@Naman 响应来自公司结构中另一个团队的微服务,它提供了这种响应格式,其中列表中只能有一个元素,因此使用 .get(0)。 (至于为什么他们决定使用列表,我不知道)。