Java8:流findFirst结果

Sun*_*ame 14 java intellij-idea optional java-8 java-stream

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

    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" 
Run Code Online (Sandbox Code Playgroud)

我不知道其他IDE如何对待它,但是我的IDE(IntelliJ)将其视为警告('Optional.get()' without 'isPresent()').我想可能它不知道你何时可以到达NoSuchElementException那里,何时不到,或者我不知道为什么.我知道有办法解决这个警告(isPresent()检查.orElse(something)),但有无用的代码,所以我不想使用这些解决方案,因为它们是如此不必要.你知道我该怎么做,或解释这是怎么回事?

编辑:对不起NPE,它有NoSuchElementException我的错误,但我认为这个问题仍然存在.

Ser*_*hyr 14

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

String fisrstString = myList.stream().findFirst().get();
service.doSomething(fisrstString);
Run Code Online (Sandbox Code Playgroud)

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

myList.stream().findFirst().ifPresent(service::doSomething);
Run Code Online (Sandbox Code Playgroud)

  • @Sunflame"可选"的monad的概念来自函数式编程.所以对我而言,这种情况下FP的优点更好 (4认同)
  • @Sunflame您可以将结果传递给`ifPresent`中的方法.`.ifPresent(结果 - > doSomething(result));` (3认同)
  • 我使用了你的sollution,还有一个'ifPresent`检查为null.目前我认为这是最好的解决方案,因为我不需要添加任何额外的未使用的值,如`.orElse(StringUtils.EMPTY)`或类似的东西 (3认同)

Eug*_*ene 8

首先你不会得到一个NPE,但是一个NoSuchElementException.其次,可能是肯定的; 但其他人可能出现并没有意识到这不会引发异常.

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

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

orElseThrow(IAmSureThisWillNotHappenException::new)
Run Code Online (Sandbox Code Playgroud)

  • 你也可以在这里抛出一个`AssertionError` (2认同)

ΦXo*_*a ツ 7

您可以毫无问题地流式传输空列表,但是如果您尝试获取空列表中的第一个元素,您将获得NoSuchElementException

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

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

String firstString = myList.stream().findFirst().orElse("Ups!");
Run Code Online (Sandbox Code Playgroud)

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

firstString = myList.stream().findFirst().orElseGet(mySupplier);
Run Code Online (Sandbox Code Playgroud)

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

firstString = myList.stream().findFirst().orElseThrow(WhatTerribleFailException::new);
Run Code Online (Sandbox Code Playgroud)
System.out.println(fisrstString);
Run Code Online (Sandbox Code Playgroud)


Fed*_*ner 6

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

myList.stream()
    .findFirst()
    .ifPresent(/* consume the string here, if present */);
Run Code Online (Sandbox Code Playgroud)

Optional.ifPresent方法接收Consumer将用来只有当Optional含有非空值.

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

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

System.out.println(myString); // pushing the object to System.out here
                              // (via the println method)
Run Code Online (Sandbox Code Playgroud)

随着Optional返回的Stream.findFirst()你在做与上面相同:

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

System.out.println(myString); // pushing the string here
Run Code Online (Sandbox Code Playgroud)

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

myList.stream()
    .findFirst()
    .ifPresent(myString -> System.out.println(myString));
Run Code Online (Sandbox Code Playgroud)

在这里,你没有获得字符串,然后将其推送到某个方法.相反,你提供的参数OptionalifPresent操作,让执行Optional推价值,你的论点.换句话说,你通过's参数拉出包裹的值.然后,只有当值存在时才会使用此参数.OptionalifPresentifPresentConsumer

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

  • @maaartinus现在我对'ifPresent`有所了解.`Optional`更适合Java 9中的任务,即它有`ifPresentOrElse`和`或`允许链``Optional`s等等 (2认同)