我一直被告知,不通过collect和findFirst等方法终止流是不好的做法,但没有真正的反馈,为什么在博客中没有太多关于它的内容。
看看下面的示例,我没有使用大规模的嵌套 if 检查,而是使用 Optional 来取回 List 值。如您所见,我的最后一步是在该流中过滤。这对我来说是预期的,这是为了取回一个列表。为什么这是错误的,我应该如何写它?
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
}
对于流,当没有终端操作时,通常不会执行任何中间操作。您的示例使用“可选”。
其操作映射
和筛选器
与流中的某些中间操作具有相同的名称,但它们是不同的。您的示例在您的问题所问的行中是可以的(不是不好的做法)。
另一件事是(正如Aomine已经指出的). orElseThrow
是获取可选
中的值并在没有异常时抛出异常的更短方法。更重要的是,使用. orElseThrow
(或. orElse
如果有默认值)更安全。Optional.get()
应尽可能避免。如果没有值,您将获得NoSuchElementException
。这几乎和不使用可选
时获取NullPointerException
一样糟糕。以适当的方式使用可选
可以保护您免受NullPointerException
的影响。
我一直被告知不通过收集和findFirst等方法终止Stream是不好的做法,但没有真正的反馈,说明为什么在博客中没有太多关于它的说法。
这实际上取决于上下文,如果你说“我是否可以用中间操作(例如过滤器
)结束一个流,而不是调用终端操作(消耗流的操作)”,那么是的,这是不好的做法,有点毫无意义,因为你刚刚定义了一些标准,但从未要求“结果”。
流是懒惰的,因为它们不做任何事情,除非被终端操作告知,例如< code>collect、< code>findFirst等。
如果你说“从方法返回流是不是不好的做法”,那么可能值得一读这个答案,关于是否应该返回流或集合。
此外,请注意,您的getBeanVia可选
逻辑正在可选上运行
如果
s在易读性、维护等方面明显更好,那么您使用可选而不是命令式的方法。所以我建议您继续使用这种方法,尽管您可以通过使用
orElseThrow
对其进行一点改进,即:
return 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)
.filter(n -> n.contains("apple"))
.orElseThrow(CustomException::new);
我试图在一个变量中保存得分为80分或80分以上的学生的姓名,但我无法使用filter进行保存,它返回整个对象,尽管我指定只打印这些对象的键值,即这些学生的姓名。 我的代码: 我怎样才能得到得分在80分以上的学生的名字?
我了解在lambda中捕获此(修改对象属性)的正确方法如下: 但我对我所看到的以下特点感到好奇: 我感到困惑(并希望得到回答)的奇怪之处在于,为什么以下方法有效: 以及为什么我无法通过引用明确捕获此内容:
我有一个代表文件夹的对象集合。我想让用户创建文件夹,因为他们喜欢与应用程序将创建一个“根”文件夹(对象)的约束,我想控制这个文件夹的_id属性。根据mongoDB文档,我应该能够设置_id字段,但是当我尝试时,我得到一个错误: mongo文档说_id可以是数组以外的任何BSON数据类型,因此我不理解为什么“0”无效。为什么我不能使用“0”作为\u id? 为了清楚起见,我希望mongoDB为根文件
大家好,我想问一下为什么我在Javascript上的过滤器只显示第一行,不能取消过滤?我是javascript的新手,我已经给了这个类一个数字来检查,但似乎不起作用,这是我的代码 null null
问题内容: 我只想知道,我们通常会在最后关闭流,但是为什么不通过以下方式关闭PrintStream 呢? 问题答案: 如果将其关闭,则将无法再写入控制台,因此,当进程终止时,让我们将此任务留给VM。您应该只关闭自己拥有或手动创建的流。不在您的控制范围之内,因此请留给创作者照顾。
我可以使用SQLDeveloper连接到远程数据库。 我试图从命令行使用sqlcl连接到同一个数据库,但我收到一个错误。 下面是我正在运行的命令: 我也尝试过: 以下是我收到的错误: 同样在SQLDeveloper中,我只是在“自定义jdbc url”下输入以下内容,它连接没有任何问题,所以我希望我可以使用相同的URL通过命令行连接,但到目前为止,它不起作用: