2017-06-09 42 views
11

我想知道,有没有办法摆脱findFirst().get()的警告,而不使用.orElse()如果我100%知道每次都有结果,所以我永远不会有一个NoSuchElementException。例如,让我们看看下面的代码:Java8:流find第一结果

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" 

我不知道其他的IDE-请客,这一点,但我的IDE(的IntelliJ)如何对待,作为一个警告('Optional.get()' without 'isPresent()')。我可能认为它不”我知道有什么方法可以解决这个警告(isPresent()检查,.orElse(something)),但无用的代码,所以我不想使用这些解决方案因为他们太没必要了。 你有什么想法我可以做什么,或解释如何处理的IDE?

编辑:对不起,NPE,其NoSuchElementException我有这个错误,但我认为这个问题仍然可用。

+2

我认为有一个选项可以禁用IntelliJ所执行的某些检查。尝试在设置 – Sweeper

+0

你找到一个空列表没有问题,但如果你尝试获得1s元素在一个空列表中,你会得到一个*** NoSuchElementException *** –

+0

https://www.jetbrains .com/help/idea/2017.1/suppressing-inspections.html#d927037e65? – slim

回答

9

那么,至于我,最好的方法是使用功能编程,并继续使用可选。所以,例如,如果您需要将此字符串传递给某个服务,您可以执行以下操作:

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

但是这看起来不太好。相反,你可以使用函数编程的优点,并做到:

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

但我不想打印它,我刚刚写了字符串,因为它非常简单明了我想要的内容,但是例如,如果我想将结果传递给方法我不能这样做,所以我必须使用警告。 – Sunflame

+3

@Sunflame你可以将结果传递给'ifPresent'中的方法。 '.ifPresent(result - > doSomething(result));' –

+4

@Sunflame Monads的思想,其中'Optional'来自函数式编程。所以对我来说,这是更好的FP的利弊它这种情况下 –

7

首先,你不会得到一个NPE,但NoSuchElementException。第二,它是谁可能肯定;但其他人可能会来,并没有意识到它不会引发异常。

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

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

orElseThrow(IAmSureThisWillNotHappenException::new) 
+0

你是对的,我不想禁用这个警告,我只是认为IntelliJ足够聪明,知道何时可以得到'NoSuchElementException'。如果结果总是在那里,那么我永远不会得到异常 – Sunflame

+1

@Sunflame,这将需要提前编译器最有可能......目前没有这样的东西可用 – Eugene

+2

你也可以在这里抛出一个'AssertionError' – gyre

3

您可以流空单没有问题,但如果你试图得到一个空的名单上的第1个要素,你会得到一个NoSuchElementException异常

的流API意识到,完美无瑕的,因此他们为您提供多种方式来处理:

选项1orElse如果没有第一个元素被发现,你可以返回一个“默认”值

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

1选项orElseGet可以使用Supplier<String>,让后面的String,如果没有第一个元素被发现

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

2选项orElseThrow你可以抛出一个异常,如果没有第一个元素被发现

firstString = myList.stream().findFirst().orElseThrow(WhatTerribleFailException::new); 

System.out.println(fisrstString); 
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将报告wa检查

IF要禁用所有合约的检查,你可以做以下操作:设置 - >检查 - >选中的一定的条件&例外选项 - >不要忘记点击应用按钮在底部保存您的设置。

IF你不想禁用除了Optional.get() warnnings你可以做以下操作的所有合同的检查:设置 - >检查 - >检查一定的条件&例外选项 - >在右下方有框架可配置Optional.get()警告 - >不要忘记点击在底部应用按钮以保存您的设置。

enter image description here

+0

是的I 'm知道'Optional'是如何工作的,所以我知道在这种情况下我可以得到NPE,但在我的情况下,我不会得到任何异常。 (对我来说不是'@ SuppressWarnings',但我不想使用这样不必要的代码) – Sunflame

+0

@Sunflame嗨,如果你想禁用这个功能,你可以在脚下看到我编辑的答案。 –

+0

它没有帮助,警告仍然存在,但我不确定是否禁用了此警告,那么当它不确定.get()的结果是否为null时,我会收到警告。 – Sunflame

4

您应使用由findFirst()而不是设法得到它的值(如果它的实际存在)返回的Optional的。

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

Optional.ifPresent方法接收​​将如果Optional包含非空值仅使用。

的问题是,我们的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()你在做上面一样Optional

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)); 

在这里,你不会得到字符串,然后推它到一些方法。相反,您提供了对OptionalifPresent操作的参数,并让Optional的实现将值推送给您的参数。换句话说,你用ifPresent的论点包裹的值OptionalifPresent将仅在该值存在时才使用此Consumer参数。

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

+1

谢谢你的解释,你是对的,我有和你说的一样的经历,我更喜欢把对象推向一个关心它的方法,在这种情况下,我必须开始思考一点点不同。所以我使用你提出的这个解决方案,你有我的+1,但是我接受@Serghey Bishyr,因为他是第一个提出这个答案的人。 – Sunflame

+0

@Sunflame不用担心,没关系。我只是在写了我的长答案的时候看到Bishyr的回答,但是我决定不会因为推拉模式拉布拉布而将其删除... –

+0

您的回答基本上与我所评论的相同,我想[我的评论](https://stackoverflow.com/questions/44458540/java8-stream-findfirst-result#comment75930588_44458623)也适用于此。 – maaartinus