How to prevent NoSuchElementException using Optional class in Java [duplicate] - java

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

Related

Why orElse block of java always get executed? [duplicate]

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

How can I return boolean value using Optional.ifPresent

I have some problems with using Optional.ifPresent statement. I would like to reduce number of NullPointerExceptions, so I decided to use Optional values.
Also I am trying to avoid a ladder of if statements anti-pattern.
So I implemented Optional.isPresent statement. But it's not really that what I expected.
Please look at these listings:
This is a part of my service:
if (getAllComputerProducers().isPresent()) {
if (isComputerProducerAlreadyExist(computerProducer))
return new ResponseEntity<>(HttpStatus.CONFLICT);
}
computerProducerRepository.save(computerProducer);
return new ResponseEntity<>(HttpStatus.CREATED);
getAllComputerProducers function looks like that:
private Optional<List<ComputerProducer>> getAllComputerProducers() {
return Optional.ofNullable(computerProducerRepository.findAll());
}
As you can see, this function returns Optional of List.
The isComputerProducerAlreadyExist function is implemented like that:
private boolean isComputerProducerAlreadyExist(ComputerProducer computerProducer) {
return getAllComputerProducers()
.get()
.stream()
.anyMatch(producer -> producer.getProducerName()
.equalsIgnoreCase(computerProducer.getProducerName()));
}
It's so much code and I believe that it could be made simpler.
My target is to reduce code to one line command like:
getAllCimputerProducers().ifPresent(***and-here-some-anyMatch-boolean-function***)
but I can't insert there a function which returns something. How can I do it?
Regards to everyone :)
You could try something like
private boolean isComputerProducerAlreadyExist(ComputerProducer computerProducer){
return this.getAllComputerProducers()
.map((List<ComputerProducer> computerProducers) -> computerProducers.stream()
.anyMatch(producer -> producer.getProducerName().equalsIgnoreCase(computerProducer.getProducerName())))
.orElse(Boolean.FALSE);
}
Or instead of loading all computer producers load only the ones using its name.
private boolean isComputerProducerAlreadyExist(ComputerProducer computerProducer){
return computerProducerRepository.findByName(computerProducer.getProducerName()).isEmpty();
}
And as far as I know Spring supports also "exist" methods for repositories without even the need to load the Entity.
The following should work
Predicate<ComputerProducer> cpPredicate = producer -> producer.getProducerName()
.equalsIgnoreCase(computerProducer.getProducerName());
boolean compProdExists = getAllCimputerProducers()
.map(list -> list.stream()
.filter(cpPredicate)
.findFirst()))
.isPresent();
You can pass the computerProducer.getProducerName() to repository to get the existing record. Method name will be 'findByProducerName(String producerName)', if producerName has unique constraint, return type will be Optional<ComputerProducer>, else Optional<List<ComputerProducer>>. However, JPA returns empty list instead of null, so optional on list is not required.

Java Optional working of orElse is not as if else

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-

Filtering List with nullable values

I trying to replace existing loop with java lambda expresions.
I have simple data structure that looks like follow:
class DbObject{
private Long objectId;
private Long basedOnObjectId; //<- this field can be null
public Long getObjectId() {
return objectId;
}
public void setObjectId(Long objectId) {
this.objectId = objectId;
}
public Long getBasedOnObjectId() {
return basedOnObjectId;
}
public void setBasedOnObjectId(Long basedOnObjectId) {
this.basedOnObjectId = basedOnObjectId;
}
}
Then I have a List of DbObjects
And I trying to filter each DbObject with specified basedOnObjectId:
(1) list.stream().filter(object -> obejct.getBasedOnObjectId()
.equals(basedOnObject.getObjectId()))
.collect(Collector.of(List))
Of course this code gives me NullPointer because some od DbObject didn't have BasedOnObjectId because they are roots.
So natural thing is to replace field "Long basedOnObjectId;" by Optional but as I mentioned at start there are existing production code co it isn't fast fix.
So I trying to make some changes, I evaluate following sentence:
Optional<Long> option = Optional.ofNullable(objectWithNullBasedOnId.getBasedOnObjectId());
And Try with .get() method or .ifPresent() but .get() also throw null pointer exception and ifPresent is not dedicated to work with stream.
I noticed that and the fact that When I have DbObject with null basedOnObjectId I don't have to check if value is exactly null but only skip this step of execution.
So I decided to use .orElse() method and return some fake value. In this case i return 0L value because this index don't exist in DB :)
So my code :
(2) List newList = list.stream().filter(object -> Optional.ofNullable(object.getBasedOnObjectId())
.orElse(0L)
.equals(basedOnObject.getObjectId()) )
.collect(Collectors.toList()) ;
And this work correctly in this case, but I think this is some kind of workaround. In other languages are possible to skip execution with null value, or use some like skip-skipWhen methods.
My question is : if exist possibility to reach the goal of (2) expression using dedicated method (in example Optional) from java 8 and write "in stream style" :)
You don't need to introduce Optional here. You just need to be aware that null is in your domain, and deal accordingly. Like this:
list.stream().filter(o -> Objects.equals(o.getBasedOnObjectId(),
basedOnObject.getObjectId()))
.collect(toList());
or by filtering out the nulls explicitly (.filter(o -> o.getBasedOnObjectId() != null) or by rolling a null check into your existing filter condition.
No reason to make this more complicated than it needs to be. Objects.equals() is likely what you want, just use that.
If you compare Optional<Long> instead of Long, there is no need for a distinction between present and absent objects.
Optional<Long> root = Optional.of(basedOnObject.getObjectId());
list.stream()
.map(DbObject::getBasedOnObjectId)
.map(Optional::ofNullable)
.filter(root::equals)
.collect(Collectors.toList());
In this case, it is even simpler, because you can just reverse the comparison:
list.stream()
.filter(o -> basedOnObject.getObjectId().equals(o.getBasedOnObjectId()))
.collect(Collectors.toList());
You probably want to actually remove the null objects from the stream before passing them to subsequent operations. Try mapping the objects to the BasedOnObjectId form and then filtering the null values:
list.stream()
.map(object -> object.getBasedOnObjectId())
.filter(object -> object != null)
...

Terminate Iterable.forEach early [duplicate]

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.

Categories

Resources