Java8:流findFirst结果

时间:2017-06-09 13:01:22

标签: java intellij-idea java-8 java-stream optional

我想知道如果我100%知道每次都有结果,有没有办法摆脱findFirst().get()警告而不使用.orElse(),所以我永远不会到达那里{ {1}}。例如,让我们看一下以下代码:

NoSuchElementException

我不知道其他IDE如何对待它,但我的IDE(IntelliJ)将其视为警告( 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" )。我想可能它不知道你什么时候能得到{'Optional.get()' without 'isPresent()' 1}}那里,什么时候不知道,或者我不知道为什么。我知道有办法解决这个警告(NoSuchElementException检查,isPresent()),但有无用的代码,所以我根本不想要使用这些解决方案,因为它们是如此不必要。 你知道我该怎么做,或解释这是怎么回事?

修改:对于NPE,我.orElse(something)抱歉,我发现了这个错误,但我认为这个问题仍然存在。

5 个答案:

答案 0 :(得分:13)

好吧,就我而言,最好的方法是使用功能编程并继续使用可选项。因此,例如,如果您需要将此字符串传递给某个服务,则可以执行以下操作:

String fisrstString = myList.stream().findFirst().get();
service.doSomething(fisrstString);

但这看起来并不那么好。相反,你可以使用功能编程的优点,并做:

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

答案 1 :(得分:8)

首先,您不会获得NPE,而是NoSuchElementException。其次,你可能确定;但其他人可能会出现并且没有意识到不会抛出异常。

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

最后一点是,如果你这么肯定,为什么不抛出异常?

orElseThrow(IAmSureThisWillNotHappenException::new)

答案 2 :(得分:6)

您应该使用Optional返回的findFirst(),而不是尝试获取其值(如果它实际存在)。

myList.stream()
    .findFirst()
    .ifPresent(/* consume the string here, if present */);

Optional.ifPresent方法会收到仅在Optional包含非空值时才会使用的Consumer

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

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

System.out.println(myString); // pushing the object to System.out here
                              // (via the println method)

Optional返回的Stream.findFirst()与上面的内容相同:

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

System.out.println(myString); // pushing the string here

另一方面,功能范例(包括Optional)通常以另一种方式起作用:

myList.stream()
    .findFirst()
    .ifPresent(myString -> System.out.println(myString));

在这里,你没有获得字符串,然后将其推送到某个方法。相反,您为Optional的{​​{1}}操作提供了一个参数,并让ifPresent的实现将值推送到您的参数中。换句话说,您通过Optional的参数 Optional包裹的值。只有当值存在时,ifPresent才会使用此ifPresent参数。

这种拉动模式在函数式编程中看得很多,并且一旦你习惯它就非常有用。它只需要我们的开发人员以不同的方式开始思考(和编程)。

答案 3 :(得分:3)

你可以毫无问题地流式传输一个空列表,但是如果你试图将第一个元素放在一个空列表中,你将得到一个 NoSuchElementException

Stream API意识到它完美无瑕,因此它们为您提供了多种处理方式:

选项1 orElse您可以返回&#34;默认&#34;如果没有找到第一个元素,则为值

String firstString = myList.stream().findFirst().orElse("Ups!");

选项2 orElseGet如果找不到第一个元素,您可以使用Supplier<String>返回字符串

firstString = myList.stream().findFirst().orElseGet(mySupplier);

选项3 orElseThrow如果找不到第一个元素,您可以抛出异常

firstString = myList.stream().findFirst().orElseThrow(WhatTerribleFailException::new);
System.out.println(fisrstString);

答案 4 :(得分:2)

IF 您知道Optional永远不会为空,您可以使用@SuppressWarnings注释,如下所示:

@SuppressWarnings("ConstantConditions") String foo = Optional.of("bar").get();

有时 Optional.get会引发NullPointerException,例如:

Optional<String> it = Optional.empty();
String foo = it.get();
          //   ^--- throws NullPointerException when this method is invoked
使用此表达式时,

SO Intellij将报告警告检查。

如果您要禁用所有合同检查,您可以执行以下操作:设置 - &gt; 检查 - &gt;取消选中常数条件&amp;例外选项 - &gt;不要忘记点击底部的应用按钮保存设置。

如果您不想禁用除Optional.get()警告之外的所有合同检查,您可以执行以下操作:设置 - &gt; 检查 - &gt;检查恒定条件&amp;例外选项 - &gt;在右下方有一个框架来配置Optional.get()警告 - &gt;不要忘记点击底部的应用按钮保存设置。

enter image description here