Java8:流findFirst结果

Java8:流findFirst结果,java,intellij-idea,java-8,java-stream,optional,Java,Intellij Idea,Java 8,Java Stream,Optional,我想知道是否有一种方法可以消除findFirst().get()上的警告,而不使用.orElse(),因为我100%地知道每次都有结果,所以我从来没有得到NoTouchElementException 例如,让我们看看以下代码: List<String> myList = new ArrayList<>(); myList.add("Test"); myList.add("Example"); myList.add("Sth");

我想知道是否有一种方法可以消除
findFirst().get()
上的警告,而不使用
.orElse()
,因为我100%地知道每次都有结果,所以我从来没有得到
NoTouchElementException

例如,让我们看看以下代码:

    List<String> myList = new ArrayList<>();
    myList.add("Test");
    myList.add("Example");
    myList.add("Sth");

    String fisrstString = myList.stream().findFirst().get(); // here I surely get "Test" 
List myList=new ArrayList();
myList.添加(“测试”);
myList.add(“示例”);
我的清单。加上(“某物”);
字符串FIRSTSTRING=myList.stream().findFirst().get();//在这里,我肯定得到了“测试”
我不知道其他IDE是如何看待这一点的,但IntelliJ将其视为一个警告

不带“isPresent()”的“Optional.get()”

我想它可能不知道什么时候你能在那里得到NoTouchElementException,什么时候没有,或者我不知道为什么。我知道有很多方法可以解决这个警告(
isPresent()
check,
.orElse(something)
),但是使用无用的代码,所以我不想使用这些解决方案,因为它们太不必要了


你知道我能做什么,或者解释一下IDE是如何处理的吗?

对我来说,最好的方法是使用函数编程并继续使用可选的。例如,如果需要将此字符串传递给某个服务,可以执行以下操作:

String fisrstString = myList.stream().findFirst().get();
service.doSomething(fisrstString);
但这看起来不太好。相反,您可以使用函数式编程的优点,并执行以下操作:

myList.stream().findFirst().ifPresent(service::doSomething);

首先,您将不会得到一个
NPE
,而是一个
NoTouchElementException
。第二,你可能会确定;但是其他人可能会出现,并且没有意识到它不会抛出异常

对于沙箱项目-是的,你不会在意,可以忽略警告;对于生产代码,我不会禁用它(即使可以)

最后一点是,如果您非常确定,为什么不抛出一个异常呢

orElseThrow(IAmSureThisWillNotHappenException::new)

您可以毫无问题地流式处理空列表,但是如果您尝试获取空列表上的第一个元素,您将得到一个NoTouchElementException

Stream API意识到这一点,因此它们为您提供了多种处理方法:

选项1
orElse
如果未找到第一个元素,则可以返回“默认”值

String firstString = myList.stream().findFirst().orElse("Ups!");
firstString = myList.stream().findFirst().orElseGet(mySupplier);
firstString = myList.stream().findFirst().orElseThrow(WhatTerribleFailException::new);
选项2
orElseGet
如果找不到第一个元素,您可以使用
供应商
返回字符串

String firstString = myList.stream().findFirst().orElse("Ups!");
firstString = myList.stream().findFirst().orElseGet(mySupplier);
firstString = myList.stream().findFirst().orElseThrow(WhatTerribleFailException::new);
选项3
或lsetrow
如果未找到第一个元素,则可以引发异常

String firstString = myList.stream().findFirst().orElse("Ups!");
firstString = myList.stream().findFirst().orElseGet(mySupplier);
firstString = myList.stream().findFirst().orElseThrow(WhatTerribleFailException::new);


如果您知道您的
可选
从不为空,您可以使用
@SuppressWarnings
注释,如下所示:

@SuppressWarnings("ConstantConditions") String foo = Optional.of("bar").get();
有时
可选。get
将引发一个
空点异常
,例如:

Optional<String> it = Optional.empty();
String foo = it.get();
          //   ^--- throws NullPointerException when this method is invoked
Optional it=Optional.empty();
字符串foo=it.get();
//^---调用此方法时引发NullPointerException
因此使用此表达式时,Intellij将报告警告检查

如果要禁用所有合同检验,可以执行以下操作:设置->检验->取消选中恒定条件和例外选项->不要忘记单击底部的应用按钮保存设置

如果您不想禁用除
可选之外的所有合同检查。get()
警告您可以执行以下操作:设置->检查->选中了恒定条件和异常选项->在右下方有一个要配置的框架
可选。get()
warnings->别忘了单击底部的应用按钮保存设置


您应该使用
findFirst()
返回的
可选的
,而不是试图获取它的值(如果它确实存在)

该方法接收一个仅当
可选
包含非空值时才会使用的值

问题是我们Java开发人员已经习惯了命令式范例。。。特别是,我们习惯于获取一个对象并推它,即推到一个方法:

String myString = "hello"; // getting an object here

System.out.println(myString); // pushing the object to System.out here
                              // (via the println method)
使用
Stream.findFirst()
返回的
可选
,您执行的操作与上面相同:

String myString = myList.stream()
    .findFirst()
    .get(); // getting a string here

System.out.println(myString); // pushing the string here
另一方面,功能范式(包括
可选
)通常以另一种方式工作:

myList.stream()
    .findFirst()
    .ifPresent(myString -> System.out.println(myString));
在这里,您不会获取字符串,然后将其推送到某个方法。相反,您为
Optional
ifPresent
操作提供一个参数,并让
Optional
的实现将值推送到您的参数。换句话说,您可以通过
ifPresent
的参数拉取
可选
所包装的值<代码>如果存在
则仅当值存在时才会使用此
使用者
参数


这种拉模式在函数式编程中非常常见,一旦您习惯了它,它将非常有用。它只需要我们开发人员以不同的方式开始思考(和编程)。

我认为有一个选项可以禁用IntelliJ所做的某些检查。尝试在设置中查找它您可以在空列表中创建一个流,没有问题,但是如果您尝试在空列表中获取1s元素,您将获得一个NoTouchElementException?我知道有可能禁用警告,但是如果禁用,则即使我需要该通知,它也不会再通知我。使用
myList.get(0)
…但我不想打印它,我只是用字符串编写,因为它很简单,我想要的东西很清楚,但例如,如果我想将结果传递给一个方法,我不能这样做,所以我必须使用带有警告的get。@Sunflame您可以将结果传递给
ifPresent
中的一个方法<代码>.ifPresent(结果->剂量测定(结果))
@Sunflame单子的概念,它是可选的,