Java 8 Optional - java

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)

Related

How to filter data on a list according to multiple parameters in Java?

I have a list of GroupOffices
List<GroupOffice> officesOfTheGroup;
I want to search whether the id is not equal to groupOffice.getId (Long value) but the label is groupOffice.getLabel (String) and assign it to a boolean. The below code is working good, but is there any better approach instead of go through all items with for loop ?
public GroupOfficeDto saveGroupOffice(GroupOfficeDto groupOfficeDto) {
List<GroupOffice> officesOfTheGroup = //some list from db..
for (GroupOffice go : officesOfTheGroup) {
if ((!go.getId().equals(groupOfficeDto.getId())) && go.getLabel().equals(groupOfficeDto.getLabel())) {
return groupOfficeDto;
}
return null:
}
Or how can I use stream ? If so, is using stream is better approach for it ?
Note: I am using Java8
If you need boolean value you can do:
boolean b = officesOfTheGroup.stream()
.anyMatch(office -> !office.getId().equals(5) && office.getLabel().equals("London"))
is there any better approach instead of go through all items with for loop ?
Notably, your code does not go through all the items if it finds an acceptable one before reaching the end of the list. But if you have only the list to work with, then there is no alternative to being prepared to check every list element. As to whether to use a for loop, I think that's just fine.
Or how can I use stream ? If so, is using stream is better approach for it ?
It is indeed pretty fashionable these days to use streams, and although they seem to be used more than I think they should, yours is not an unreasonable use case. You might write it like this:
public GroupOfficeDto saveGroupOffice(GroupOfficeDto groupOfficeDto) {
List<GroupOffice> officesOfTheGroup = //some list from db..
Integer officeId = groupOfficeDto.getId();
String officeLabel = groupOfficeDto.getLabel();
return officesOfTheGroup.stream()
.filter(o -> !o.getId().equals(officeId))
.anyMatch(o -> o.getLabel().equals(officeLabel))
? groupOfficeDto : null;
}
Particularly relevant here is use of the .anyMatch() terminal operation, because it allows stream processing to finish as soon as the result is determined, like your for loop, rather than processing the entire stream. Also note that the ID and Label against which you are comparing the offices are extracted and stored in variables before the stream expression. This allows them to be "effectively final", as is necessary for them to appear in the lambdas in the stream. It's also slightly more efficient to do it this way, instead of retrieving the same objects from the DTO over and over again -- for the for loop case, too.
Do note that the stream version is not much simpler than the loop version, and not much easier to read, either. I don't personally see much advantage for either one over the other.
Try this:
public GroupOfficeDto saveGroupOffice(GroupOfficeDto groupOfficeDto) {
...
List<GroupOffice> result = officesOfTheGroup.stream()
.filter(it -> it.getLabel().equals(groupOfficeDto.getLabel()))
.filter(it -> !it.getId().equals(groupOfficeDto.getId()))
.collect(Collectors.toList())
...
}

Return Optional as it is if the returned Optional has value, else call another function [duplicate]

This question already has answers here:
Get value from one Optional or another
(5 answers)
Closed 4 years ago.
I have two methods func1 and func2 which return Optional.
Return Optional as it is if the returned Optional from func1 has value, else call func2 and return its Optional.
One way is to use if-else.
Optional<MyObject> opt1 = func1();
if (opt1.isPresent()) {
return opt1;
}
return func2();
However, I wish to achieve it using Java 8 Optional and avoid if-else.
Something like:
return Optional.of(obj1)
.flatMap_returnOptionalIfvaluePresent(func1)
.orElseReturnOptionalFromThis(func2)
Can anyone suggest a good way for it?
Edit: or
Java 9 and later offer a very elegant solution:
Optional<String> myFunc() {
return func1().or(this::func2);
}
or (introduced in Java 9) does exactly what you asked for: If the Optional returned from func1 has a value, it is returned (or an equivalent Optional). If not, the supplier (here func2()) is invoked to get an Optional, which is then returned.
Java 8
There are several ways. In Java 8 I prefer to take the values out of the Optionals from func1 and func2:
Optional<String> myFunc() {
String returnValue = func1().orElse(func2().orElse(null));
return Optional.ofNullable(returnValue);
}
Edit 2: #Holger’s alternative suggestion in a comment is good enough for quoting within the answer (Holger, you may have posted it as a comment only because the question is closed and you therefore could not post your own answer):
return func1().map(Optional::of).orElse(func2());
It goes the opposite way: The mapping using Optional::of wraps the Optional from func1 inside yet an Optional only if it has a value, from which orElse unwraps it again.
If the call to func2 is expensive, you may want to avoid it when it’s not needed (when func1 supplies a value):
String returnValue = func1().orElseGet(() -> func2().orElse(null));
Or in Holger’s version:
return func1().map(Optional::of).orElseGet(this::func2);
isPresent used in a couple of other answers is so low-level, I seldom use it and only as a last resort.
If you're using java 9+, you can just use Optional.or:
return func1().or(() -> func2());
In Java 8, you may need to create a new Optional from results (use orElseGet to avoid eager execution):
return Optional.ofNullable(func1().orElseGet(() -> func2().orElse(null)));
What about something like
Object value1 = func1();
return value1.isPresent() ? value1 : func2();
Unless I've misunderstood what you're after that will return the value from the first function if it's present, and if it doesn't exist then call func2() to return the second optional. You could probably simplify it further to func1().isPresent but it made it a little less clear.
It would be something lke this, if i usterstand everything correctly:
Optional.of(obj1)
.filter(obj -> func1().isPresent())
.orElse(func2());
Here is a more generic version, working with n functions:
private static <T> Optional<T> firstPresent(Supplier<Optional<T>>... optionals) {
return Stream.of(optionals)
.map(Supplier::get)
.filter(Optional::isPresent)
.findFirst()
.orElse(Optional.empty());
}
To be used like this:
Optional<String> result = firstPresent(() -> func1(null), () -> func2("abc"));

Java8 way to handle if..else check in Collections

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.

Based on condition set object value and return boolean using java 8 streams

I have nested list and am able to set isMatched and department.setMatchedStatus(true) when if condition is true.
boolean isMatched = false;
for (Employee employee: company.getEmployees()) {
for (Department department: employee.getDepartments()) {
if(departmentList.contains(department.getDepartmentName())){
isMatched = true;
department.setMatchedStatus(true);
}
}
}
return isMatched;
Would like to achieve the same using java 8 streams, which i tried using below code, but couldn't return boolean.
isMatched = company.getEmployees().stream()
.flatMap(employee-> employee.getDepartments().stream())
.filter((department) -> departmentList.contains(department.getDepartmentName()))
.forEach((department) -> department.setMatchedStatus(true));
Could anyone help me on this please ?
The difficulty here is that you have two side effects you want performed: setting the matched state on the Department object, and setting a local flag value to determine if there were any matches. The approach of using peek and count in sisyphus' answer will work, since in this case we can be assured that count won't short-circuit. However, it may cause problems under maintenance. If somebody were to copy and rearrange this code, it might silently break because of short-circuiting, and this would be quite subtle.
Perhaps a better approach is to pack the side effects into the forEach operation. This uses AtomicBoolean as a mutable "box" to work around the inability to mutate captured local variables. It's also preferable to the single-element array trick, as the atomics are safe in case the stream is run in parallel.
This also uses a statement lambda, which I generally prefer to avoid. In this case it's not too bad, and it makes clear that multiple side effects are occurring.
AtomicBoolean isMatched = new AtomicBoolean(false);
company.getEmployees().stream()
.flatMap(employee -> employee.getDepartments().stream())
.filter(department -> departmentList.contains(department.getDepartmentName()))
.forEach(department -> {
department.setMatchedStatus(true);
isMatched.set(true);
});
return isMatched.get();
You could use the 'peek()' method on the Stream, which allows you to consume the items in the stream without altering the contents of the stream. After you've updated each object you just need to know if any were matched.
return company.getEmployees().stream()
.flatMap(employee-> employee.getDepartments().stream())
.filter((department) -> departmentList.contains(department.getDepartmentName()))
.peek((department) -> department.setMatchedStatus(true))
.count() > 0;
To me, the most clear solution would be the following:
Set<Department> matchingDepartments =
company.getEmployees().stream()
.flatMap(employee -> employee.getDepartments().stream())
.filter(department -> departmentList.contains(department.getDepartmentName()))
.collect(Collectors.toSet());
matchingDepartments.forEach(department -> department.setMatchedStatus(true));
return !matchingDepartments.isEmpty();
It's somewhat less efficient as produces an intermediate Set, but looks better than other proposed variants from the code readability point of view.

using Java8's Optional<T> in a functional way for updating source with default value

This is probably more a question about functional programming than about Java 8 specifically, but it's what I'm using right now.
I have a source object (could represent a repository, or a session..., doesn't matter here) that has a method retrieveSomething() that returns an Optional<SomethingA>.
I have a method somewhere that returns a Something, by calling retrieveSomething() and providing a default value in case the optional was empty, as follows:
return source.retrieveSomething()
.orElseGet(() -> provideDefaultValue());
Now I want to modify this code so that in case the source didn't contain any value yet (so the optional was empty), the source is updated with the provided default value.
Of course, I could easily do that inside a lambda expression code block:
return source.retrieveSomething()
.orElseGet(() -> {
Something sth = provideDefaultValue()
source.putSomething(sth);
return sth;
});
But if I understand correctly, I'm not supposed to use functions that cause side effects. So what's the "correct" (functional) way to do this, keeping the benefit of using Optional (in real code I'm actually also performing a map operation on it, but that's irrelevant here) ?
You could follow the way Java does this with Map.computeIfAbsent()
which takes a second parameter which is a function on how to compute and insert the record:
So your code would become:
Something something = source.computeIfAbsent(sth, (k)->provideDefaultValue());
An advantage of using a lambda to compute the default instead of just passing it in, is the lambda will only be evaluated if it needs to be so if computing the default is expensive, you only have to pay it when you need it.
From a conceptual standpoint, you use the optional pattern to deal with the absence of a return value. This means, if your source instance doesn't contain a value for you to use, you have the choice of providing a default value to use in its place.
It is not advised to modify the Optional directly to provide its value; that instance may be temporal and will differ on subsequent calls to retrieve it.
Since a function call truly governs what's returned by that Optional, the only approach you have if you truly want to go down this route is to modify how that value is computed. This really should be done from within the function providing the Optional, but it could be done outside of it if necessary.
Since there's not enough code structure here to truly write up some example, I will describe the steps:
Outside of the method providing the Optional, you write the same closure as you did before, with the side effect of adjusting the value used to compute the original Optional. This is likely a field of some sort.
Inside of the method providing the Optional, you ensure that you don't expose provideDefaultValue anywhere else (since they won't need it), and use a boolean conditional before you package the Optional.
return value == null ? Optional.of(provideDefaultValue()) : Optional.of(value);
...but that really defeats the purpose of the Optional, as you're still doing a null check.
A slightly better approach to the above would be to compute value in such a way that it was either itself or the default value, and return the Optional of that...
value = computeValue();
if(null == value) {
value = provideDefaultValue();
}
return Optional.of(value);
...but again, seriously defeating the purpose of Optional, as you're doing null checks.
An answer I came up with myself, which I'm not entirely satisfied with, but may serve as an example of what I'm looking for:
I could implement something similar to a Pair<V1,V2> class and then map the Optional<Something> to a Pair<Something, Boolean> where the Boolean value would indicate whether or not the value was a generated default:
Pair<Something, Boolean> somethingMaybeDefault =
source.retrieveSomething()
.map(sth -> new Pair<Something, Boolean>(sth, false))
.orElseGet(() -> new Pair<Something, Boolean>(provideDefaultValue(), true));
Then I'd update in case the boolean is false:
if (somethingMaybeDefault.value2()) {
source.putSomething(somethingMaybeDefault.value1());
}
And finally return the new value:
return somethingMaybeDefault.value1();
Of course, this uses imperative style for the update, but at least the functions remain pure.
I'm not sure this is the best possible answer though.

Categories

Resources