Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
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?
–
–
–
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).
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.
–
–
–
–
–
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);
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)
–
–
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.
–
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.