This question already has answers here:
Chaining Optionals in Java 8
(10 answers)
Closed 1 year ago.
I am trying to get value from multiple Optional based on priority and condition
Lets say in following two set of optional the activitys that can be return are Walking and Swimming. If there is any activity in either of the optional and if swimming is there, then swimming should get preference else walking. If there are no activities then this will return empty. I managed to write it but there are too many conditions and wanted to see if there is a smart way of avoiding so many conditions
public Optional<Activity> getActivity(){
Optional<Activity> activityWhenSunShines= getActivityWhenSunShiningForUser(u);
Optional<Activity> activityWhenDayIsGood= getActivityWhenDayIsGoodForUser(u);
if(activityWhenSunShines.isPresent() && Activity.SWIMMING == activityWhenSunShines.get()){
return activityWhenSunShines;
}else if(activityWhenDayIsGood.isPresent() && Activity.SWIMMING == activityWhenDayIsGood.get()){
return activityWhenDayIsGood;
}else if(activityWhenSunShines.isPresent()){
return activityWhenSunShines;
}else if(activityWhenDayIsGood.isPresent()){
return activityWhenSunShines;
}else{
return Optional.empty();
}
}
This code
activityWhenSunShines.isPresent() && Activity.SWIMMING == activityWhenSunShines.get()
can be converted to a more functional style, without isPresent followed by get
activityWhenSunShines.map(a -> a == Activity.SWIMMING).orElse(false)
The last 3 cases can be replaced with Optional.or (added in Java 9).
That gives you:
Optional<Activity> activityWhenSunShines = getActivityWhenSunShiningForUser(u);
Optional<Activity> activityWhenDayIsGood = getActivityWhenDayIsGoodForUser(u);
if(activityWhenSunShines.map(a -> a == Activity.SWIMMING).orElse(false)){
return activityWhenSunShines;
} else if(activityWhenDayIsGood.map(a -> a == Activity.SWIMMING).orElse(false)){
return activityWhenDayIsGood;
}
return activityWhenSunShines.or(() -> activityWhenDayIsGood);
Patient: Doctor, doctor! It hurts when I smash this hammer against my face!
Doctor: Okay. Stop doing that then.
Optional (in the java ecosystem, at least) is mostly bad. It's fine for stream terminal return values and not much else.
The much better alternative is to just have a data structural setup where neither null nor Optional are relevant. The next-best alternative is to use null (and add some nullity annotations if you prefer compile-time checks). A very distant crappy third solution is the dreaded Optional.
For example, here, why not have an Activity.NOTHING, and spec gAWSSFU to never return null?
Here's what your code would look like if you did that:
Activity activityWhenSunShines = getActivityWhenSunShiningForUser(u);
Activity activityWhenDayIsGood = getActivityWhenDayIsGoodForUser(u);
return
(activityWhenSunShines == Activity.SWIMMING || activityWhenDayIsGood) ? Activity.SWIMMING :
activityWhenSunShines != Activity.NOTHING ? activityWhenSunShines :
activityWhenDayIsGood;
If instead of nothing you prefer null here, it's the exact same code, just replace Activity.NOTHING with null and you're good to go.
Optional doesn't compose (generics has co/contra/in/legacy-variance, in order to be composable. The nullity dimension introduced by Optional doesn't play that game; you e.g. can write a method that takes in a list of Number or some subclass thereof. You can't write a (type-safe) method that takes a list of either String or Optional<String>. Optional is also entirely backwards incompatible (e.g. map.get(x) does not return Optional<V> and never will, given that java doesn't break backwards compatibility, especially not of such an oft-used method). If you want compile-time-checked null safety, have a look at null annotation frameworks, such as the one baked into your IDE (both Eclipse and IntelliJ have their own system, fully supported with compile time checks), or use e.g. checker framework's, which is more flexible than what eclipse and intellij offer.
Related
We have all seen that kind of code
if (myObject!= null
&& myObject.mySubObject() != null
&& myObject.mySubObject().getSpecificValue() != null
&& !myObject.mySubObject().getSpecificValue().isEmpty()
) {
......
}
How could I write this the clean way ?
You can do chaining with Optional:
Optional.ofNullable(myObject)
.map(o -> o.mySubObject())
.map(so -> so.getSpecificValue())
.map(sv -> sv.isEmpty())
.orElse(false)
Or with method references even shorter (does the same):
Optional.ofNullable(myObject)
.map(Foo::mySubObject)
.map(Bar::getSpecificValue)
.map(Baz::isEmpty)
.orElse(false)
where Foo, Bar and Baz are the names of the respective classes.
If you are using someone else's code then you're really stuck handling for a possible null. On the other hand, if you have control over the code base then never return a null object, and make that a rule across your entire application.
This may sound bad at first but I have developed several enterprise-level applications and this is a very effective way to make the code consistent and much more readable.
So, now, this
if (myString != null && !myString.isEmpty()) {
becomes simply
if (!myString.isEmpty()) {
In lue of that option use the new Optional feature in J8 as it is intended for that purpose.
Consider the usage of this expression:
String hi = Optional.ofNullable(sayHi()).orElse("-");
which effectively corresponds to this ternary expression:
String hi = sayHi() != null ? sayHi() : "-";
Is this usage of Optional.ofNullable with a method call a good practice? Or just extra verbose coding?
I recognise that Optional.ofNullable actually creates a variable and avoids calling the sayHi() method twice. To avoid this problem you actually could create an extra variable but this adds to the verbosity of the ternary option:
String hi = sayHi();
hi = hi != null ? hi : "-";
On the other hand Optional.ofNullable creates in case of hi not being null an extra Optional object. So there is for sure more overhead to it.
So there seem to be some pros and cons to using this type of construct to replace the ternary constructor.
By the way: this is the Java 8 implementation of Optional.ofNullable:
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
In JDK 9 or later, use this:
String hi = Objects.requireNonNullElse(sayHi(), "-");
This avoids having to repeat sayHi() if a ternary operator is used, or to assign its value to a local variable that is reused within the ternary. It might be a small improvement. It also sidesteps the question of whether to use Optional. :-)
Whenever I come to think of using the Optional API for a specific purpose I always remind my self of what it was intended to do and why it was brought into the JDK and i.e.
Optional in intended to provide a limited mechanism for library method
return types where there is a clear need to represent “no result” and
where using null for this is overwhelmingly likely to cause errors - Stuart Marks
Optional is primarily focused on a return type that might or might not have a return value.
Over using this construct like in this specific example of yours just causes extra memory allocation and GC overhead.
I’d keep things simple and instead do:
String hi = sayHi();
if(hi == null) hi = “-“;
...
Is this usage of Optional.ofNullable with a method call a good practice?
Conceptually, it's a bad practice. The basic idea is to represent the absence of a return value, not to wrap everything that might be null. I am strongly against this usage.
Or just extra verbose coding?
It looks to me like a failed attempt to make your code more fashionable. ("Look, we are using brand-new Optional from Java 8!")
I prefer readability and clarity over conciseness.
This Optinal usage doesn't provide clarity but raises questions:
Why do you wrap the variable?
What are you going to do with this Optional?
Will it be used/returned below?
It doesn't give brevity either: your second line is even shorter.
To avoid this problem you actually could create an extra variable but this adds to the verbosity of the ternary option.
You aren't creating an extra variable. The one-line version could be:
String hi = (hi = sayHi()) != null ? hi : "-";
Though, your two-line suggestion is absolutely fine:
String messageContent = sayHi();
String hi = messageContent != null ? messageContent : "-";
If you're going to allow Optional into your workflow then you should consider modifying the sayHi() method so that it returns Optional<String> which will make the result more elegant:
hi = sayHi().orElse("-");
If you don't want to introduce Optional into your workflow (because it does create an additional object to contain the optional value) then you're better off sticking with simple null checks and the ternary operator.
With regard to the performance costs of Optional (such as increased garbage collection), you'd need to profile your application and decide whether or not this was a real concern.
Additionally, if you're mostly interested in String then be aware of the Objects.toString(Object, String) method which return a default value if the object is null:
hi = Objects.toString(hi, "-");
This is tidier and more elegant than writing out the code manually.
In brief: avoid the Optional type.
The main argument for Optional on return types is, "It's too easy for clients to forget to handle the possibility of a null return value. Optional is ugly and in your face, so a client is less likely to forget to handle the possibility of an empty return value. Everywhere else, programmers should continue to use normal references, which might be null."
I wrote a discussion of the pros and cons of using Java's Optional type: Nothing is better than the Optional type.
I think it's mostly a matter of personal taste.
From my point of view it would be more meaningful to just return an Optional<String> and let the caller deal with a missing value.
Optional, being a monadic type, can be leveraged for more then just getting an alt-value.
On the other end your operator seems terse enough, if used consistently it could be practical.
I don't think performance is a big issue here.
In Java 8,
I currently have a lambda that looks like this:
.createSomething((acceptableStates, someProxy) -> (userId) ->
acceptableStates.contains(someProxy.getSomeAttributeId(userId)))
However, we have changed someProxy.getSomeAttributeId to return an Optional<String> instead of a string.
What's the cleanest / most accepted way to essentially check for if acceptableStates contains the value of someProxy.getSomeAttributeId(userId) if the attribute returned isn't empty?
(Note: acceptableStates is still a list of strings, not of Optional<String>)
.... userId -> someProxy.getSomeAttributeId(userId)
.map(acceptableStates::contains)
.orElse(Boolean.FALSE);
Unfortunately, I see no very clean solution here. Refer to this question: Functional style of Java 8's Optional.ifPresent and if-not-Present?
Additionally, you even have to save the optional in a variable if the call to getSomeAttributeId does cost resources.
.createSomething((acceptableIds, someProxy) -> (userId) ->
{
Optional<String> attrId = someProxy.getSomeAttributeId(userId);
return attrId.isPresent() ? acceptableStates.contains(attrId.get()) : false;
})
I strongly recommend writing understandable and clear code like this snippet:
Optional<SomeAttributeId> optional = someProxy.getSomeAttributeId(userId);
return optional.isPresent() && acceptableStates.contains(optional.get());
If there should not be thrown an exception (1) when someProxy.getSomeAttributeId(userId) is an empty optional:
acceptableStates.contains(someProxy.getSomeAttributeId(userId).orElseThrow(() -> new Exception()))
Or unless you have the default value (2) to fill up the result with:
acceptableStates.contains(someProxy.getSomeAttributeId(userId).orElse(DEFAUT_VALUE))
My point:
Do not pursue Java 8 features which will mess everything up, especially in cases where a simple boolean expression could be used. I had experience refactoring some code toward plain Java statements because new people (1.1) came in a project could not get what the code does. With the time, even I (as a writer) barely can do so (1.2).
Also, with that "lambda chain" style, one slight change could cause rewriting a snippet/method entirely (2).
It is always fun to poke around n-nested lambdas, where n > 2 (3).
Anyway, if you don't share my point, #Eugene proposed a good way to go with.
return value.isPresent() && value.get().contains("some-text");
Is this a valid (intended) usage of Optional type in Java 8?
String process(String s) {
return Optional.ofNullable(s).orElseGet(this::getDefault);
}
I'll take another swing at this.
Is this a valid usage? Yes, in the narrow sense that it compiles and produces the results that you're expecting.
Is this intended usage? No. Now, sometimes things find usefulness beyond what they were originally for, and if this works out, great. But for Optional, we have found that usually things don't work out very well.
Brian Goetz and I discussed some of the issues with Optional in our JavaOne 2015 talk, API Design With Java 8 Lambdas and Streams:
link to video
link to slides
The primary use of Optional is as follows: (slide 36)
Optional is intended to provide a limited mechanism for library method return types where there is a clear need to represent "no result," and where using null for that is overwhelmingly likely to cause errors.
The ability to chain methods from an Optional is undoubtedly very cool, and in some cases it reduces the clutter from conditional logic. But quite often this doesn't work out. A typical code smell is, instead of the code using method chaining to handle an Optional returned from some method, it creates an Optional from something that's nullable, in order to chain methods and avoid conditionals. Here's an example of that in action (also from our presentation, slide 42):
// BAD
String process(String s) {
return Optional.ofNullable(s).orElseGet(this::getDefault);
}
// GOOD
String process(String s) {
return (s != null) ? s : getDefault();
}
The method that uses Optional is longer, and most people find it more obscure than the conventional code. Not only that, it creates extra garbage for no good reason.
Bottom line: just because you can do something doesn't mean that you should do it.
Since this is more or less an opinion-based question, I'll throw mine in. If you're trying to say
if (id == 1) {
Foo f = new Foo(id, "Bar", "US");
return "Bar".equals(f.getName()) && "US".equals(f.getCountryCode());
} else {
return false;
}
then just say that. Making things "functional" doesn't automatically make things clearer or better. By introducing a needless Optional, a couple lambdas, and some Optional methods that I had to look up, you've made the code more convoluted and difficult to understand. I don't think the designers of Java "intended" for people to use Optional to help make code more obscure.
EDIT: After reading some responses, I think it's worth adding some comments. This is not a functional programming idiom I'm familiar with, which would make it harder to understand. The idioms I am familiar with mostly involve Java streams, or (in other languages) functional idioms applied to multiple values in arrays or lists or other collections of multiple values. In those cases, once you get past the unfamiliarity, the functional syntax can be seen as an improvement because it allows some details to be hidden (loop indexes, iterators, running pointers, accumulator variables). So overall, it can simplify things. This example, by itself, doesn't do any such simplification.
However, some of the Optional features are useful in stream contexts. Suppose we had a parseInt() method that returns an Optional<Integer>, which is empty if the input string is invalid. (Java 8 really should have provided this.) This would make it easy to take an array of strings and produce an array of integers in which the strings that don't parse are simply eliminated from the result--use parseInt in a stream map(), and use a stream filter to filter out the empty Optionals. (I've seen multiple StackOverflow questions asking how to do this.) If you want to keep only the positive values, you could use an Optional.filter() to change the nonpositives to Optional.empty() before using the stream filter (although in this case, you could add another stream filter afterwards, but in a more complex case the Optional filter could be more useful). That's what I see as the main benefit of Optional from a functional standpoint. It allows you to work with a collection of values all at once, by giving you a way to represent "non-values" and write a function that will still work with them. So I guess the main use of Optional, besides a replacement for null, would be to represent empty spaces in a sequence of values while you're applying functions to the entire sequence as a whole.
Asking whether it's "valid" is rather opinion-based, but as to whether it's the intended use case: no, it's not.
Brian Goetz, Oracle's language architect for Java, has stated that the use case for Optional is for when you need a "no value" marker, and when using null for this is likely to cause errors. Specifically, if a reasonable user of your method is not likely to consider the possibility that its result is null, then you should use Optional. It was explicitly not intended to be a general "Maybe"-type object, as you're using it here.
In your case, the method that returns the Optional is private. That means it can only be used by the implementers of the class, and you can assume that they have good knowledge of the class' methods — including which of them may return null. Since there's no reasonable risk of confusion, Brian Goetz would (probably) say that he would not consider this a valid use case.
Its a little contrived, but 'valid' (as in 'syntactically') , but as #yshavit pointed to, it was intended for use in library development.
Previous answer was due to FP code being difficult to read. Below is commented(a little verbose, b/c that is the javadoc comments) but still. Much easier to read IMHO. (2nd is no-comments, and at least alignment to help readability)
private boolean isFooValid(final Integer id) {
return getFoo(id)
// filter if 'f' matches the predicate, return Optional w/f if true, empty Optional if false
.filter(f -> "Bar".equals(f.getName()) && "US".equals(f.getCountryCode()))
// If a value is present, apply the provided mapping function to it,
// If non-null, return an Optional describing the result.
.map(f -> true)
// Return the value if present, otherwise return other.
.orElse(false);
}
Or at least line it up so its more apparent what is going on and easier to read.
private boolean isFooValid(final Integer id) {
return getFoo(id)
.filter(f -> "Bar".equals(f.getName()) && "US".equals(f.getCountryCode()))
.map(f -> true)
.orElse(false);
}
I find stuff like this rather annoying and ugly in equals methods:
if (field == null)
{
if (other.field != null)
return false;
}
else if ( ! field.equals(other.field))
return false;
In C# I could've done this:
if( ! Object.Equals(field, other.field))
return false;
Is there something similar in Java, or what is the preferred way to do this kind if thing?
Java 7 offers java.util.Objects.equals.
Use commons-lang:
org.apache.commons.lang.ObjectUtils.equals(Object object1, Object object2)
Source code:
public static boolean equals(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if ((object1 == null) || (object2 == null)) {
return false;
}
return object1.equals(object2);
}
From Apache
http://commons.apache.org/lang/
That's about equivalent to what you do in C#
Guava equal which does this :
public static boolean equal(#Nullable Object a, #Nullable Object b) {
return a == b || (a != null && a.equals(b));
}
or null object pattern
Guava also has the somewhat related comparison chain and a load of other goodies.
I would write it this way:
return field != null && other.field != null && field.equals(other.field);
which is not as elegant as the C# code line, but much shorter then the if tree you posted.
I accept all answers technically. Practically I will not use any of them in code I have under control because all provided solutions are working around the core problem: null-values. KEEP YOUR CORE MODEL FREE FROM NULL VALUES, and the question is obsolete in this case.
At system borders like third party libraries one has to deal with null values sometimes. They should converted into meaningful values for the core model. There the given solutions are helpful.
Even if Oracle recommends the equals-Methods to be null-safe, think about that: Once you accept null values your model it is getting fragile. The equals-method will not be the last method where you will check for null. You have to manage null-checks in your method call hierarchy. Methods may not be reusable out of the box anymore. Soon, every parameter will be checked for null.
I saw both sides:
On one side code full of null checks, methods that trust not a single parameter anymore and developers that are afraid to forget a null check.
On the other side code with full expressive statements that make clear assertions to have full functioning objects that can be used without fear of NullPointerExceptions.
As part of the Project Coin, there was a proposal for adding a series of null-safe operators to Java. Sadly, they didn't make it into Java 7, maybe they'll appear in Java 8. Here is the general idea of how they would work
Actually everyone follows there own way to do this and also i would like to introduce groovy here.
There is one way
field == null ? false : true; // So basically it will return true when it is not null.
In groovy there is null safe operator for objects. Lets take an example for class
A {
String name = "test1"
String surName = "test2"
public String returnName() {
return name + surName
}
}
A a = null
a?.name
// Mentioned operator ? will actually check whether a is null or not. then it will invoke name.
Note: i didn't applied semi colon in code as this is not require in groovy.
String.valueOf() will solve some of those problems if the toString is implemented for your classes. It will spit out the toString() answer or "null" if the pointer is null.
Use == operator when you are checking for object references, if both the references refers same object it will return true. Otherwise if you are looking for object content then go with .equals method of objects.
So null means it doesn't have any memory location given in heap. So it can be simply checked with '==' operator.