Java8 way to handle if..else check in Collections - java

Below one is my code and I would like to write a better equivalent code in Java8
List<String> fruits = Arrays.asList("Apple","Orange","Banana");
List<String> animals = Arrays.asList("Tiger","Lion","Monkey");
#SuppressWarnings("all")
Map<String,List<String>> allLists = new HashMap() {{
put("fruits",fruits);
put("animals",animals);
}};
Legacy prior Java8 way of checking
if(allLists.get("fruits")!=null) {
List<String> fruits1 = allLists.get("fruits");
if(fruits1.contains("Apple")) {
System.out.println("Apple is there");
}
}
Java8 Way of doing..
Consumer<List<String>> consumer1 = arg ->{
Optional.of(arg.contains("Apple")).filter(value -> value.equals(true)).ifPresent(value1 -> System.out.println("Apple is available"));
};
Optional.of(allLists.get("fruits")).ifPresent(consumer1);
Currently the Java8 way is returning the output "Apple is available"..
Question is, How do I handle if Apple is not in the ArrayList...
Ex: If Apple is not in the list , I want to print "Apple is not Available"
Please suggest me better approaches to handle both cases.

I'd go for getOrDefault on the map, like this:
if(allLists.getOrDefault("fruits", Collections.emptyList()).contains("Apple"))
System.out.println("Having apples");
Basically, this eliminates the key-not-present check you normally do. In situations, where you want to continue to work with the list (grouping in maps), you may also check out computeIfAbsent.

First, Optional.of will throw a NullPointerException if you pass null to it. You need to use ofNullable here as
Optional.ofNullable(allLists.get("fruits"))
Optional in Java 8 does not have a method that can be executed if a value is not found.
But Java-9 has ifPresentOrElse that takes a Runnable where you can print that Apple is not there

FWIW, Optional is not replacement for null. Cleverly use of Optional in place of null and simple if...else checks is bad idea.
Why Optional: Optional's are created to handle value/no values(empty) cases on Streams. Optional's are created to avoid breaking stream methods for null check during fluent chaining.
Until you have a valid reason to create Optional, do not create it.
ex: The below is not a good Idea,
String process(String s) {
return Optional.ofNullable(s).orElseGet(this::getDefault);
}
//Better way is
String process(String s) {
return s!=null ? s : getDefault();
}
PITFALLS: Optional.get is a really attractive method to use but beware that Optional.get throws "NoSuchElementException". Not similar to get method in java Collections ( they wont throw exception if the value does not present).
So use get method along with isPresent() method.
Places you should not use Optional:
Do not create Optional type Fields
Do not use Optional Parameters (forcing someone to create empty
optional instead of passing null is really bad)
Do not combine Java collections with Optional.

Related

Java Optional - Sorting a Nullable List stored as a property of a Nullable object

How can I approach sorting with an Optional?
Both mainProducts or productSublist in the code below maybe null. The resulting list productSubList should be sorted by Date.
List<ProductSubList> productSubList = Optional.of(mainProducts)
.map(MainProducts::getProductSubList)
.ifPresent(list -> list.stream().sorted(Comparator.comparing(ProductSubList::getProductDate))
.collect(Collectors.toList()));
The code shown above produces a compilation error:
Required type: ProductSubList ; Provided:void
Part Answer which seems too long, is there a way to make this shorter?
if (Optional.of(mainProducts).map(MainProducts::getProductSubList).isPresent()) {
productSublist = mainProducts.getProductSubList().stream()
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.collect(Collectors.toList());
}
Resource: How to avoid checking for null values in method chaining?
Seems you're looking for something like this:
List<ProductSubList> productSubList = Optional.ofNullable(mainProducts)
.map(MainProducts::getProductSubList)
.map(list -> list.stream()
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.collect(Collectors.toList()))
.orElse(Collections.emptyList());
Avoid using Optional to replace Null-checks
Optional wasn't designed to perform null-checks, and there's nothing wrong implicit null-check to begin with. Yes, if there are plenty of null-checks the code can become unreadable very quickly, but it's rather a design issue than a problem with the tools offered by the language.
The best remedy for the code that suffers from null-checks is to reduce the number of nullable fields, in the first place. In some cases it's fairly easy to achieve, especially if we are talking about Collections of Arrays like in this case, simply assign an empty Collection by default. This suggestion can be found in many places, for instance, see item "Return empty collections or arrays, not nulls" of the classic book "Effective Java", by Joshua Bloch.
Regarding the usage Optional.ofNullable() here's quote from the answer by Stuart Marks, Java and OpenJDK developer:
The primary use of Optional is as follows:
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.
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.
With that being said, if you would follow the advice to avoid keeping a nullable Collection and quite using Optional for null-checks the code can be written in a very simple well-readable manner.
Assuming your domain classes look like that (Lombok's #Getter annotation is used for conciseness):
#Getter
public static class ProductSubList {
private LocalDateTime productDate;
}
#Getter
public static class MainProducts {
private List<ProductSubList> productSubList = new ArrayList<>(); // or Collection.emptyList() if the class is mean only to carry the data and doesn't expose methods to modify the list
}
Which would give the following code:
if (mainProducts == null) return Collections.emptyList();
return mainProducts.getProductSubList().stream()
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.toList();
Pretty much self-explanatory. That would be the best option if can modify the classes you're using.
If for some reason, you can't modify MainProducts and/or you've provided a simplified version and there are much more nullable moving parts, here a few more options.
Stream.ofNullable()
You can make use of the Java 9 Stream.ofNullable():
List<ProductSubList> productSubList = Stream.ofNullable(mainProducts)
.flatMap(mainProd -> Stream.ofNullable(mainProd.getProductSubList()))
.flatMap(Collection::stream)
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.toList();
Note it's not a silver bullet, and I'm not saying to "plug Stream.ofNullable() everywhere". Excessive usage Stream.ofNullable() might create confusion because in it might seem there more levels of nesting than it's really is.
Stream.mapMulti()
We can reduce the number of stream operations and rearrange the code in a more readable way with Java 16 Stream.mapMulti():
List<ProductSubList> productSubList1 = Stream.ofNullable(mainProducts)
.<ProductSubList>mapMulti((mainProd, consumer) -> {
List<ProductSubList> prodSubLists = mainProd.getProductSubList();
if (prodSubLists != null) prodSubLists.forEach(consumer);
})
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.toList();
Personally, I think the version above is good enough, but if you're unhappy with null-checks in the stream and want to see fancy one-liners, here's how it can be rewritten:
List<ProductSubList> productSubList2 = Stream.ofNullable(mainProducts)
.<ProductSubList>mapMulti((mainProd, consumer) ->
Objects.requireNonNullElse(
mainProd.getProductSubList(), List.<ProductSubList>of()
).forEach(consumer)
)
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.toList();
Also see:
Should Optional.ofNullable() be used for null check?
Uses for Optional

How to use Java Optional to elegantly replace Ternary operators

A super simple question:
Here's my plain Java code using traditional ternary operator ?
public DateTime getCreatedAt() {
return !recordA.isPresent() ? recordB.get().getCreatedAt() : recordA.get().getCreatedAt();
}
My best bet is following:
public DateTime getCreatedAt() {
return recordA.map(
record -> record.getCreatedAt())
.orElse(recordB.get().getCreatedAt());
}
This could compile, but looks like it's not behaving correctly.
It always executes both branches, for e.g. when recordA isPresent(), it still executes recordB.get().getCreatedAt() which throws me
java.util.NoSuchElementException: No value present
Any help is appreciated!
Basically, I'd like to replace the traditional ternary operator with more advanced Optional/lamda features.
To avoid eagerly evaluating else-branches, use orElseGet, which takes an instance of the functional interface Supplier:
return recordA.map(
record -> record.getCreatedAt())
.orElseGet(() -> recordB.get().getCreatedAt());
You're looking for .orElseGet(() -> recordB.get().getCreatedAt()); and the reason to that can be found on this post --> Difference between Optional.orElse() and Optional.orElseGet()
Some people may find it a bit subjective but personally, I'd say by default, it makes more sense to use orElseGet() as opposed to orElse every time except in the case where the default object is already constructed as this will prevent many unexpected problems (given you didn't read the differences between orElse and orElseGet doc) as such of the one you're facing now.
read more from Java Optional – orElse() vs orElseGet()
My question about recordB being Optional got unanswered but if it is Optional then you cannot just safely call its get method, you need to check if it is empty or not. Here safe call to get record or null if both recordA and recordB are empty Otionals.
recordA
.map(Record::getCreatedAt)
.orElseGet( () -> recordB.map(Record::getCreatedAt).orElse(null) );
If you are using Java 9+, you may be able to use ifPresentOrElse() method as more completely explained in this Stackoverflow answer.
recordA.ifPresentOrElse(
value -> recordA.get().getCreatedAt(),
() -> recordB.get().getCreatedAt()
);

Why does Java stack Optionals?

I'm generally very happy with the design of the Java language but today I came across a strange design choice.
I don't know any platform where you can suggest changes to the Java language for version 9 or 10 and therefore I'm writing this issue here.
With Optionals you have a much better control over the behaviour if a value is null.
Today I mapped a value in a stream to an Optional.
I was really surprised, that findFirst then gives me a Optional<Optional<T>> instead of just Optional<T>.
Where is the point in having Optional<Optional<T>>?
For Java 9 and Streams this is solved with .flatMap(Optional::stream) but this is only a work around and boilerplate code.
Wouldn't it be much better if Optionals generally wouldn't stack and always flats down?
Optional<Optional<T>> => Optional<T>
Optional.of(Optional.of("")) => Optional.of("")
Further explanation:
Working with Optionals you don't care if the sub optional was null or if the actual object was null. It always would come down to Optional.empty().
String s = null;
Optional<String> opt = null;
Optional.of(s) => Optional.empty()
Optional.of(opt) => Optional.empty()
Also if you are working with optionals you are only interested in the object. So if you try to get the object you always have to double get and check the optional.
if(optionalOfOptional.isPresent()) {
optional = optionalOfOptional.get();
if(optional.isPresent()) {
objectOfInterest = optional.get();
}
}
I even see this being a source for errors since you would always need to check both optionals if you condition on your object being present.
if(optionalOfOptional.isPresent() && optionalOfOptional.get().isPresent()) {
...
}
Only checking the first optional could easily lead to mistakes.
In addition, why would it make sense to have a Optional that is null in the first place? Isn't optional there to get rid of working with null?
On the method level this could be solved for sure.
For example Optional.of could look something like:
public static <T> Optional<T> of(T value) {
return value instanceof Optional ? value : new Optional<>(value);
}
On the type level this is probably not that easy.
It simply doesn't make sense to forbid Optional<Optional<T>>.
Let's say you've got a List<Optional<T>>. The following lists are different:
List<Optional<T>> listA = Arrays.asList(Optional.empty());
List<Optional<T>> listB = Arrays.asList();
They're obviously different: the first is non-empty, the second is empty.
Correspondingly, the result of invoking findFirst() on their streams is different:
System.out.println(listA.stream().findFirst().isPresent()); // true
System.out.println(listB.stream().findFirst().isPresent()); // false
Now, I know about the meaning of the data in those lists that Java can't possibly know. Let's say that the lists contain the results of invoking a list of Callable<Optional<T>>s. In that case, there might be an important difference to my application between:
I invoked N>0 callables, and all of them returned Optional.empty()
I invoked zero callables.
So I really don't want the language or API to assume that there's no difference between the two, and converting the Optional<Optional<T>> to an Optional<T>.
And since a List<E>.stream().findFirst() always returns an Optional<E>, there's no way to prevent an Optional<Optional<T>> without preventing me creating a List<Optional<T>> (or Collection, Set, HashMap<K, Optional<T>> etc). So, you'd basically have to completely disallow nested generics, which would be a major loss of functionality.
I'm quite contented with the existence of Optional<Optional<T>>, as it is entirely consistent with the rest of the language. If you don't like them, just avoid creating them; but don't think that's right for everybody else.
I talk about this elsewhere that an Optional<T> should never be null. It violates what Optional<T> promises: getting rid of NullPointerExceptions.
Therefore, I think it is a deficient design in the Optional API to allow Optional<Optional<T>>. The methods to get instances of Optional should behave better when given an Optional. But that being said, they can't. They could be accomplished if Optional.of was overloaded except for one slight issue.
Since you can have a generic type T that is of type Optional, you can't have two Optional.of methods (one for Optional and one for T). Occasionally it would prevent some code from compiling if someone had the bright idea to have an Optional<Optional<T>>. Take the below code, it will fail to compile.
package otherCode;
public class Abc<T> {
public static void main(String[] args) {
Abc<B> test1 = new Abc<>();
test1.foo(new A());
test1.foo(new B());
Abc<Base> test2 = new Abc<>();
test2.foo(new A());
test2.foo(new B());
Abc<A> test3 = new Abc<>();
// these two don't compile
test3.foo(new A());
test3.foo(new B());
}
public void foo(A item) {
System.out.println("Foo");
}
public void foo(T item) {
System.out.println("bar");
}
public static class Base {
}
public static class A extends Base {
}
public static class B extends Base {
}
}
Without forcing a language and syntax change on the entire language (forbidding a Optional<Optional<T>>) the automatic conversion is not an easy task.
Java 8 in general I found took developers a while to grasp. When it first came out, I'd see Map<String, Optional<T>> when Map<String, T> would have sufficed or I did see Optional<Optional<T>>. I even saw Map<Optional<T>, Optional<Set<Optional<T>>>> instead of simply Map<T, Set<T>>. As time progressed and people grappled with the language, I feel we learned to better manage these typing and get more sensible typing.
I think it is unfortunate Java doesn't do the conversion automatically but for the poor soul who may need an Optional<Optional<T>> one day, I'm willing to use map, flatMap, orElse, and ofNullable every once in awhile to keep my typing sane. Using those methods may help with your particular quandaries.
Edit:
I see, either missed it or an edit, that OP saw that Stream<Optional<T>>.first returns an Optional<Optional<T>>. What OP intends to do affects a compromise. They could .map the stream to strip the interior Optional or they could .filter & .map the stream to strip out empty Optionals. One sad, extra line of code.

Calling contains on a list for an optional value in Java?

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

Java 8 Optional

I want to check if a particular object size is greater than 0. If it is greater than 0 then I want to create an optional object, if not then I want to return an Optional empty. This is the long version of the java code:
if(fooA.size>0) {
return Optional.of(new Foo());
} else {
return Optional.empty();
}
Is there any way to compact this into one line using java 8's optional library?
Is there any way to compact this into one line using java 8's optional library?
If you insist on using the Optional class, you could use Optional.ofNullable() and just pass it null if the condition isn't met:
return Optional.ofNullable(fooA.size > 0 ? new Foo() : null);
Note, however (as Holger correctly states) that using the Optional class doesn't give you any significant1 advantage over just replacing your if/else statement with a ternary one (as tobias_k and Holger have both done in their comments):
return fooA.size > 0 ? Optional.of(new Foo()) : Optional.empty();
1 The first line is a little shorter, which I usually consider an advantage, but an absolutely insignificant one in this case, as the length difference is negligible.
Imperative Way
If you decide to stick to imperative programming, an if-else construct as yours is good as it is. Its readable, understandable and you gain nothing by simply reducing lines of code (unless you get paid for that and want to game the system).
The (condition)?(true-branch):(false-branch) construct is nice but may become poorly readable if it gets too complex. Some auto-format rules put each part of it into separate lines anyway. So think before using it.
The simplest way for putting the creation into a single line is to refactor the instantiation into a separate method and invoke it:
return newOptionalFoo(fooA.size > 0);
...
private Optional<Foo> newOptionalFoo(boolean condition) {
if(condition) {
return Optional.of(new Foo());
} else {
return Optional.empty();
}
}
If you want to condense this to single line - imperative style - do this:
return condition ? Optional.of(new Foo()) : Optional.empty();
Functional Way
In case you want to use functional programming, you should not mix functional and imperative programming when it is avoidable.
A proper functional way would be to wrap fooA into an Optional, filter on the condition and map to Foo. So if condition is not fulfilled, it is mapped to the empty Optional. I'd prefer this way.
return Optional.of(fooA).filter(f -> f.size > 0).map(f -> new Foo());
Alternatively you could create the Optional of Foo and use the filter so that the optional becomes empty if the filter condition does not match:
return Optional.of(new Foo()).filter(f -> fooA.size > 0);
But this would create an instance of Foo regardless of the condition beeing true or false. If you want to have lazy instantiation because creating a Foo is expensive, you could use a Supplier and map to Foo after filtering
return Optional.of((Supplier<Foo>) Foo::new)
.filter(s -> fooA.size > 0)
.map(Supplier::get)

Categories

Resources