简体   繁体   English

Java8:流 findFirst 结果

[英]Java8 : stream findFirst result

I want to know if there is a way to get rid of the warning at findFirst().get() without using .orElse() when I know 100% that every time there is a result, so I never get a NoSuchElementException .我想知道是否有一种方法可以在不使用.orElse()情况下消除findFirst().get()的警告,因为我 100% 知道每次有结果时,所以我永远不会得到NoSuchElementException

For example let's see the following code:例如让我们看看下面的代码:

    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" 

I don't know how other IDEs treat this, but IntelliJ treats that as a warning我不知道其他 IDE 是如何处理的,但 IntelliJ 将其视为警告

'Optional.get()' without 'isPresent()' 'Optional.get()' 没有 'isPresent()'

I think probably it doesn't know when can you get NoSuchElementException there and when not, or I have no idea why.我想它可能不知道什么时候可以在那里得到NoSuchElementException ,什么时候不能得到,或者我不知道为什么。 I know there are ways to solve this warning( isPresent() check, .orElse(something) ) but with useless code, so simply I don't want to use those solutions because they are so unnecessary.我知道有办法解决这个警告( isPresent() check, .orElse(something) )但是代码无用,所以我不想使用这些解决方案,因为它们太不必要了。

Do you have any idea what can I do, or explain how is that treated by the IDE?你知道我能做什么吗,或者解释一下 IDE 是如何处理的?

Well, as for me, the best way is to use functional programing and continue to work with optional.嗯,对我来说,最好的方法是使用函数式编程并继续使用可选的。 So, for example if you need to pass this string to some service, you can do:因此,例如,如果您需要将此字符串传递给某个服务,您可以执行以下操作:

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

But this looks not so good.但这看起来不太好。 Instead you can use the pros of functional programing, and do:相反,您可以使用函数式编程的优点,并执行以下操作:

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

You should make use of the Optional returned by findFirst() instead of trying to get its value (if it's actually present).您应该使用findFirst()返回的Optional而不是尝试获取其值(如果它确实存在)。

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

The Optional.ifPresent method receives a Consumer that will be used only if the Optional contains a non-null value. Optional.ifPresent方法接收一个只有在Optional包含非空值时才会使用的Consumer

The problem is that we Java developers are so used to the imperative paradigm... In particular, we are used to getting an object and pushing it ie to a method:问题是我们 Java 开发人员太习惯命令式范式了......特别是,我们习惯于获取一个对象并将它送到一个方法:

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

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

With the Optional returned by Stream.findFirst() you were doing the same as above:随着Optional的返回Stream.findFirst()你在做与上面相同:

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

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

On the other hand, the functional paradigm (including Optional ) usually works the other way:另一方面,函数范式(包括Optional )通常以另一种方式工作:

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

Here, you don't get the string and then push it to some method.在这里,您没有获得字符串,然后将其推送到某个方法。 Instead, you provide an argument to Optional 's ifPresent operation and let the implementation of Optional push the value to your argument.相反,您为OptionalifPresent操作提供一个参数,并让Optional的实现将值推送到您的参数。 In other words, you pull the value wrapped by the Optional by means of ifPresent 's argument.换句话说,你被包裹值Optional借助ifPresent的说法。 ifPresent will then use this Consumer argument, only if the value is present. ifPresent然后将使用此Consumer参数,仅当该值存在时。

This pull pattern is seen a lot in functional programming and is very useful, once you get used to it.这种拉取模式在函数式编程中很常见,一旦你习惯了它,它就会非常有用。 It just requires us developers to start thinking (and programming) in a different way.它只是要求我们开发人员以不同的方式开始思考(和编程)。

First you will not get a NPE , but a NoSuchElementException .首先,您不会得到NPE ,而是NoSuchElementException Second, it's you who might be sure;其次,可能有把握; but other people might come along and don't realize that it will not throw an exception.但其他人可能会一起走,并没有意识到,它不会抛出异常。

For a sandbox project - yes you would not care and can ignore the warning;对于沙箱项目 - 是的,您不会关心并且可以忽略警告; for production code I would not disable it (even if you could).对于生产代码,我不会禁用它(即使可以)。

And the last point is that if you are so sure, why not throw an exception?最后一点是,如果您如此确定,为什么不抛出异常?

orElseThrow(IAmSureThisWillNotHappenException::new)

you can stream an empty list without a problem, but if you try to get the 1st element on an empty list you will get a NoSuchElementException您可以毫无问题地流式传输空列表,但是如果您尝试获取空列表中的第一个元素,您将获得NoSuchElementException

the Stream API is aware of that flawless therefore they offer you multiple ways to handle that: Stream API 意识到了这一点,因此它们为您提供了多种处理方式:

Option1 : orElse you can return a "default" value if no 1st element is found选项 1orElse ,如果未找到第一个元素,您可以返回“默认”值

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

Option2 : orElseGet you can use a Supplier<String> that gives back a String if no 1st element is found选项2: orElseGet你可以使用一个Supplier<String> ,如果没有第一个元素被发现,还给一个String

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

Option3 : orElseThrow you can throw an exception if no 1st element is found选项3: orElseThrow如果没有第一个元素被发现,你可以抛出一个异常

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

System.out.println(fisrstString);

IF you know your Optional never be empty, you can use @SuppressWarnings annotation as below:如果您知道您的Optional永远不会为空,您可以使用@SuppressWarnings注释,如下所示:

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

Sometimes Optional.get will be raising a NullPointerException , for example:有时Optional.get会引发NullPointerException ,例如:

Optional<String> it = Optional.empty();
String foo = it.get();
          //   ^--- throws NullPointerException when this method is invoked

SO when this expression is used Intellij will reporting a warnning inspection.因此,当使用此表达的Intellij将报告一个WARNNING检查。

IF you want to disable all contract inspection you can do the following actions: Settings -> Inspections -> unchecked the Constant condition & exceptions option -> don't forget to click Apply button at bottom to saving your settings.如果您想禁用所有合同检查,您可以执行以下操作:设置->检查-> 取消选中常量条件和例外选项 -> 不要忘记单击底部的应用按钮以保存您的设置。

IF you don't want to disable all contract inspection except Optional.get() warnnings you can do the following actions: Settings -> Inspections -> checked the Constant condition & exceptions option -> at the right bottom side there is a frame to configure Optional.get() warnnings -> don't forget to click Apply button at bottom to saving your settings.如果您不想禁用除Optional.get()警告之外的所有合同检查,您可以执行以下操作:设置->检查-> 选中常量条件和异常选项 -> 在右下角有一个框架配置Optional.get()警告 -> 不要忘记单击底部的应用按钮来保存您的设置。

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM