This question already has answers here:
Difference between `Optional.orElse()` and `Optional.orElseGet()`
(9 answers)
When I need to use Optional.orElseGet() over Optional.orElse()
(3 answers)
Closed 2 years ago.
I was playing with Java's Optional and thought that it works like an if else block. But in the following code even if the name variable is not null the content of the orElse block get's executed. Any explanation?
import java.util.Optional;
class Scratch {
public static void main(String[] args) {
String name = "some text";
System.out.println(
Optional.ofNullable(name)
.map(n -> mapped())
.orElse(getOrElse()));
}
static String mapped(){
System.out.println("mapped -- block executed");
return "mapped";
}
static String getOrElse(){
System.out.println("orElse -- block executed");
return "orElse";
}
}
Output:
mapped -- block executed
orElse -- block executed
mapped
Have a closer look at Optional.orElse(T). It takes a value which needs to be provided to that call but that value will only be returned in the else case. So getOrElse() will be executed to get that value in any case.
Optional.orElse(T) is normally used with already existing values, e.g. like this: map(e -> mapped()).orElse("not found")
If you want to use a function that will only be called in the else case you need to use Optional.orElseGet(Supplier<? extends T>) like this: map(e -> mapped).orElseGet(Scratch::getOrElse) (or orElseGet(() -> getOrElse())).
the orElse part is not being executed. Your getOrElse method is being executed in order to pass a value into orElse, but when the Optional is evaluated the orElse branch isn't retruned.
If you want to lazily evaluate it, you could use orElseGet and pass a method reference to it:
Optional.ofNullable(name)
.map(n -> mapped())
.orElseGet(Scratch::getOrElse));
Related
This question already has answers here:
java.util.NoSuchElementException: No value present even though we use stream
(2 answers)
Closed 9 months ago.
While filtering through a list of user defined class type using Stream API has been encountered some cases where no element has been found in the list for given condition.
How to prevent exception in such case and handle according to business logic using optional class?
Stream API method looks like :
public static Optional<Policy> getPolicy(ReturnTermPolicy policyType,
String policyKey) {
Optional<Policy> policy = Optional.of(policyType.getPolicies().stream()
.filter(temp -> temp.getPolicyKey().equals(policyKey))
.findFirst().get());
return policy;
}
The calling code looks like that:
Optional<Policy> updatedPolicyOptional = getPolicy(updatedPolies,policykey); // <- exception is being generated here
if (updatedPolicyOptional.isPresent()) {
// business logic
}
else {
// business logic
}
Output :
Verify audit report for update made in TC_08
java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:135)
There's no need to extract the result from the optional object just in order to wrap it with an optional again.
It's pointless and will trigger NoSuchElementException if result is not present. To solve the problem, remove the call of get() which both unsafe and redundant in this case:
public static Optional<Policy> getPolicy(ReturnTermPolicy policyType,
String policyKey) {
return policyType.getPolicies().stream()
.filter(temp -> temp.getPolicyKey().equals(policyKey))
.findFirst();
}
In order implement your conditional logic fluently you can make use of Optional.ifPresentOrElse() which expects a Consumer that would be executed if result is present and a Runnable that will be fired in case if optional is empty. Note, this method is accessible with Java 9.
getPolicy(updatedPolies,policykey).ifPresentOrElse(policy -> doSomething(policy),
() -> doSomethingElse());
With Java 8 you can use Optional.ifPresentOrElse() that expects consumer and can cave the if part of conditional logic. And for the case of empty optional, you will need a condition.
Optional<Policy> policy = getPolicy(updatedPolies,policykey);
policy.ifPresentOrElse(policy -> doSomething(policy));
if (!policy.isPresent()) doSomethingElse();
findFirst() already returns an Optional, trying to get() it leads to an error when it is empty. So your function should be:
public static Optional<Policy> getPolicy(ReturnTermPolicy policyType,
String policyKey) {
return = policyType.getPolicies().stream()
.filter(temp -> temp.getPolicyKey().equals(policyKey))
.findFirst();
}
And depending on your Java version (and your business logic) you can use things like:
Java 8.
if (updatedPolicyOptional.isPresent()) {
// business logic
}
else {
// business logic
}
or
T value = updatedPolicyOptional(mapToTFunctor).orElse(someTValue);
Java 9.
updatedPolicyOptional.ifPresentOrElse(someConsumer,someNoParamFunctor);
I want to reuse stream object in my method, but when I call second time from supplier I saw stream has already been operated upon or closed error.
private Stream<User> getUserStream(Stream<User> testStream) {
Supplier<Stream<User>> supplierUserStream=()->userStream;
supplierUserStream.get().sorted();
supplierUserStream.get().sorted();// throw exception Stream has already been operated upon or closed
return userStream;
}
I don't want to convert stream to a list. I saw a lot of examples like that.
Supplier<Stream<User>> streamSupplier
= () -> Stream.of(userStream.toArray(size -> new User[size]));
Look at the message closely (emphasis mine):
java.lang.IllegalStateException: stream has already been operated
upon or closed
Since there is no terminal operation in your first statement, your stream has not been closed but has been operated upon which is the reason why you are getting the error when you try to operate on it the second time.
You can change it as follows to get rid of the error:
supplierUserStream.get().sorted().sorted();
ONLINE DEMO
However, it will be a kind of hiding a potential problem e.g. if you replace the test call in main, with the following statement, you will again get the same problem:
getStringStream(Stream.of("Hello", "World")).forEach(System.out::println);
A good way to deal with it can be as suggested by ernest_k:
It can also be resolved by keeping track of derived stream objects.
Stream stream = s.get().sorted(); stream = stream.sorted();
return stream.sorted();, to reuse those redundant sort() calls.
Demo:
import java.util.function.Supplier;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
getStringStream(Stream.of("World", "Hello", "Good morning!")).forEach(System.out::println);
}
private static Stream<String> getStringStream(Stream<String> testStream) {
Supplier<Stream<String>> supplierStringStream = () -> testStream;
Stream<String> stream = supplierStringStream.get().sorted();
return stream.sorted();
}
}
Output:
Good morning!
Hello
World
In Optional while optional.orElse method is call, irrespective of the element is present or not the orElse part is executed it does not behave as the if else condition.
In the below code if you see in Case 1 both getNullPoJo and getDefaultPoJo is executed since getNullPoJo will return empty Optional
In Case 2 where you will get a Optional with loaded value (from getLoadedPoJo) also you getDefaultPoJo is executed
I am just trying to understand the working of optional.orElse.
public static void main (String [] a) {
PoJo poJo1=getNullPoJo().orElse(getDefaultPoJo());//Case 1
System.out.println("pojo1 Got "+poJo1.getVariable());
PoJo poJo2=getLoadedPoJo().orElse(getDefaultPoJo());//Case 2
System.out.println("pojo2 Got "+poJo2.getVariable());
}
private static Optional<PoJo> getNullPoJo() {
System.out.println("Executing getNullPoJo");
Optional<PoJo> optional=Optional.empty();
return optional;
}
private static Optional<PoJo> getLoadedPoJo() {
System.out.println("Executing getLoadedPoJo");
PoJo poJo =new PoJo();
poJo.setVariable("Loaded");
Optional<PoJo> optional=Optional.of(poJo);
return optional;
}
private static PoJo getDefaultPoJo() {
System.out.println("Executing getDefaultPoJo");
PoJo poJo =new PoJo();
poJo.setVariable("Default");
return poJo;
}
The current Output is:
Executing getNullPoJo
Executing getDefaultPoJo
pojo1 Got Default
Executing getLoadedPoJo
Executing getDefaultPoJo
pojo2 Got Loaded
My Expected Output is:
Executing getNullPoJo
Executing getDefaultPoJo
pojo1 Got Default
Executing getLoadedPoJo
pojo2 Got Loaded
I do not want the call to getDefaultPoJo in Case 2
Use orElseGet() to avoid evaluating getDefaultPoJo() when the Optional is not empty:
PoJo poJo1=getNullPoJo().orElseGet(() -> getDefaultPoJo());
PoJo poJo2=getLoadedPoJo().orElseGet(() -> getDefaultPoJo());
getNullPoJo().orElse(getDefaultPoJo());
It's a method chain, and every method in this chain will get executed, no matter how the underlying API is supposed to work.
1) getNullPoJo()
2) r = getDefaultPoJo()
3) orElse(r)
In order to execute a method, its actual parameters must be evaluated. To call orElse(getDefaultPoJo()), getDefaultPoJo() must be invoked as well. That's the reason you are getting more than you expected.
Usually, you will see
.orElse(null);
.orElse(defaultValue);
where null, and defaultValue are predefined values that don't require any calculations.
On the other hand, we write
.orElseGet(() -> generateDefaultValue());
.orElseGet(() -> calculateDefaultOutcome());
where generateDefaultValue and calculateDefaultOutcome are methods that do perform some calculations (intensive ones or ones we don't want to execute until the right moment [your case]).
Compare,
.orElseGet(() -> createDefaultPoJo());
.orElse(DEFAULT_POJO);
where DEFAULT_POJO is a variable initialised prior to this method call, and createDefaultPoJo() is a method that creates a default instance every time it gets called.
The output is correct, Optional.orElse() will allways execute the else-action. (the expression you provide) Use orElseGet() -which only calls the function if Optional.isPresent == false- for your desired output:
Difference between `Optional.orElse()` and `Optional.orElseGet()`
https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#orElseGet-java.util.function.Supplier-
This question already has answers here:
How to execute logic on Optional if not present?
(14 answers)
Closed 4 years ago.
I have the following block of code:
Optional<Integer> result = //some method that returns an Optional<Integer>;
if(result.isPresent()) {
return result.get();
} else {
return 0;
}
and my IntelliJ suggests that I replace it with a functional expression. I see that there is a method ifPresentOrElse() inside Optional but I can't possibly figure out how to use it in this particular case.
Any suggestions? Thanks!
Looks like orElse() is what you'd want here. https://docs.oracle.com/javase/9/docs/api/java/util/Optional.html#orElse-T-
Optional<Integer> result = //some method that returns an Optional<Integer>;
return result.orElse(0);
This question already has answers here:
Limit a stream by a predicate
(19 answers)
Closed 8 years ago.
I have a set and a method:
private static Set<String> set = ...;
public static String method(){
final String returnVal[] = new String[1];
set.forEach((String str) -> {
returnVal[0] += str;
//if something: goto mark
});
//mark
return returnVal[0];
}
Can I terminate the forEach inside the lambda (with or without using exceptions)?
Should I use an anonymous class?
I could do this:
set.forEach((String str) -> {
if(someConditions()){
returnVal[0] += str;
}
});
but it wastes time.
implementation using stream.reduce
return set.parallelStream().reduce((output, next) -> {
return someConditions() ? next : output;
}).get(); //should avoid empty set before
I am looking for the fastest solution so exception and a 'real' for each loop are acceptable if they are fast enough.
I'm reluctant to answer this even though I'm not entirely sure what you're attempting to accomplish, but the simple answer is no, you can't terminate a forEach when it's halfway through processing elements.
The official Javadoc states that it is a terminal operation that applies against all elements in the stream.
Performs an action for each element of this stream.
This is a terminal operation.
If you want to gather the results into a single result, you want to use reduction instead.
Be sure to consider what it is a stream is doing. It is acting on all elements contained in it - and if it's filtered along the way, each step in the chain can be said to act on all elements in its stream, even if it's a subset of the original.
In case you were curious as to why simply putting a return wouldn't have any effect, here's the implementation of forEach.
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
The consumer is explicitly passed in, ad this is done independently of the actual iteration going on. I imagine you could throw an exception, but that would be tacky when more elegant solutions likely exist.