Java8 : stream findFirst result

66,221

Solution 1

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

Solution 2

You should make use of the Optional returned by findFirst() instead of trying to get its value (if it's actually present).

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.

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 i.e. to a method:

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:

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:

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. In other words, you pull the value wrapped by the Optional by means of ifPresent's argument. ifPresent will then use this Consumer argument, only if the value is present.

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.

Solution 3

First you will not get a NPE, but a 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)

Solution 4

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

the Stream API is aware of that flawless therefore they offer you multiple ways to handle that:

Option1: orElse you can return a "default" value if no 1st element is found

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

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

Option3: orElseThrow you can throw an exception if no 1st element is found

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

System.out.println(fisrstString);

Solution 5

IF you know your Optional never be empty, you can use @SuppressWarnings annotation as below:

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

Sometimes Optional.get will be raising a NullPointerException, for example:

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.

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.

enter image description here

Share:
66,221

Related videos on Youtube

Sunflame
Author by

Sunflame

Updated on July 15, 2022

Comments

  • Sunflame
    Sunflame almost 2 years

    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.

    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

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

    I think probably it doesn't know when can you get NoSuchElementException there and when not, or I have no idea why. 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.

    Do you have any idea what can I do, or explain how is that treated by the IDE?

    • Sweeper
      Sweeper almost 7 years
      I think there is an option for disabling certain checks that IntelliJ does. Try looking for it in the settings
    • ΦXocę 웃 Пepeúpa ツ
      ΦXocę 웃 Пepeúpa ツ almost 7 years
      you cna stream an empty list without a problem, but if you try to get the 1s element on an empty list you will get a NoSuchElementException
    • Tomato
      Tomato almost 7 years
    • Sunflame
      Sunflame almost 7 years
      I know there is a possibility to disable the warning, but if I disable then it wont notify me anymore even if I need that notification,.
    • Holger
      Holger almost 7 years
      Use myList.get(0)
  • Sunflame
    Sunflame almost 7 years
    But I don't want to print it, I have just wrote with Strings because its so simple and clear what I want, but for example if I want to pass the result to a method I cannot do this way so I have to use get with the warning.
  • Sergii Bishyr
    Sergii Bishyr almost 7 years
    @Sunflame You can pass the result to a method inside of ifPresent. .ifPresent(result -> doSomething(result));
  • Sunflame
    Sunflame almost 7 years
    You are right, I don't want to disable the warning, I just thought that IntelliJ is enough smart to know when I can get NoSuchElementException. If the result is always there then I never get the exception
  • Eugene
    Eugene almost 7 years
    @Sunflame that would require an ahead of time compiler most probably... and no such thing is available at the moment
  • Sergii Bishyr
    Sergii Bishyr almost 7 years
    @Sunflame The idea of monads, which Optional is, comes from functional programming. So for me it's better to pros of FP it this case
  • Sunflame
    Sunflame almost 7 years
    I used your sollution, there is also a check in ifPresent for null. At the moment I think it is the best solution since i don't have to add any additional unused value like in .orElse(StringUtils.EMPTY) or something like this
  • Sunflame
    Sunflame almost 7 years
    Yes I'm aware of how the Optional works, so I know I can get NPE in this case, but in my case I wont get any Exception. (For me is not working the @SuppressWarnings but I don't want to use unnecessary code like this)
  • holi-java
    holi-java almost 7 years
    @Sunflame hi, if you want to disable this capability you can see my edited answer at foot.
  • Sunflame
    Sunflame almost 7 years
    It does't helped, the warning is still there, but I am not sure if I disable any warning for this, then will I get the warning when it is not sure that the .get()'s result is null or not.
  • holi-java
    holi-java almost 7 years
    @Sunflame Hi, if you don't want to disable all contract inspection there is an option for that in the right bottom frame.
  • Sunflame
    Sunflame almost 7 years
    Thank you the explanation, you are right, I have same experiences like you said, I prefer that to push the object to a method that cares about it, and I have to start thinking a little bit different, in such cases like this. So I use this solution that you have suggested, you have got my +1 but I give the accept to @Serghey Bishyr because he was the first who suggested this answer.
  • fps
    fps almost 7 years
    @Sunflame No worries, it's OK. I just saw Bishyr's answer while writing my long answer, but I decided to not remove it because of the push vs pull pattern blablabling...
  • WorldSEnder
    WorldSEnder almost 7 years
    Other people could come along and wonder what happens if the element is not present. I think actually asserting the claim made in the question would be a better way
  • gyre
    gyre almost 7 years
    You could also throw an AssertionError here
  • Sergii Bishyr
    Sergii Bishyr almost 7 years
    @WorldSEnder not agree. I think it's obvious that action happens only ifPresent. And I think that it's much better to use FP technique when using FP structures such as Optional.
  • maaartinus
    maaartinus almost 7 years
    @SergheyBishyr Sometimes, it's correct to do nothing when the list is empty. Sometimes, an empty list is an error and then you blew it, as by doing nothing you hide the problem. This isn't about FP, it's about failing fast. I guess, orElseThrow helps, but you lose the fluent syntax.
  • maaartinus
    maaartinus almost 7 years
    Your answer is basically the same as the one I commented on, and I guess, my comment applies here, too.
  • Sergii Bishyr
    Sergii Bishyr almost 7 years
    @maaartinus I guess this is a topic for another discussion an it depends on the functionality. And I'm not saying that throwing an exception is bad. It depends
  • fps
    fps almost 7 years
    @maaartinus OP clearly stated that he/she didn't want to use orElse. Of course, you can use orElseGet or orElseThrow if needed.
  • fps
    fps almost 7 years
    @maaartinus In Java 9 Optional has been extended to support more operations. You should use the one that suits you best.
  • maaartinus
    maaartinus almost 7 years
    @FedericoPeraltaSchaffner I wasn't recommending orElse, but orElseThrow (or(() -> throw ...) from Java 9 might be better). The OP wrote "if I 100% know there is every time a result" and whenever I'm 100% sure, I add an assertion, just in case the 100% estimate was slightly off. And that's my problem with the FP style here as there's no checkPresent() allowing me to write myList.stream().findFirst().checkPresent().ifPresent(....).
  • fps
    fps almost 7 years
    @maaartinus That depends on what you want to do, and even on personal taste. I personally don't like assertions and I don't think I should always throw an exception if the expectation is not met. If this was a test, then yes, I should make the test fail, but programming business logic isn't like creating tests. Sometimes it's OK to throw an exception and sometimes it's OK to do nothing, or to return a default value, or even to do something else. My point was to just use the Optional instead of getting its value.
  • maaartinus
    maaartinus almost 7 years
    @FedericoPeraltaSchaffner Agreed, throwing in production is not always right. Sometimes logging a failed assumption is all we can do. Ignoring it is sometimes the right thing and what I dislike about ifPresent is that it makes the ignorance to the obvious choice without making us think (no warning like with get).
  • fps
    fps almost 7 years
    @maaartinus Now I get your point regarding ifPresent. Optional is much better suit to the task in Java 9, i.e. it has ifPresentOrElse and or allows to chain Optionals, etc