Java 8 Optional instead of if - java

I have problem with Optional and I don't know how to handle it.
public void check(String name) {
if (name != null)
doSomething(name);
else
doMore();
}
How to change this if into Optional?

There is a very neat method for that, but present in jdk-9...
public void check(String name){
Optional.ofNullable(name)
.ifPresentOrElse(YourClass::doSomething, YourClass::doMore);
}
assuming doSomething and doMore are static methods... If not an instance should be used, like this::doSomething or this::doMore

While there certainly is a way to create the same code using Optionals (e.g. see Eugene's answer) you should not use Optionals here (imho).
Either you would get the Optional passed into your method which creates a overhead for the caller and does not really make sense looking at why / for what use case Optional was introduced.
Or you would create the Optional yourself inside the method. That is more "okay" but very cumbersome, obscures what is actually happening and I would request it to be changed if I came across it during a code review. Just compare the snippet using an Optional and your current code - your code is probably shorter in terms of characters, it is obvious what is happening. The only upside of using Optionals here is that it seems to become a one-liner which is firstly nothing that is more important than readability and furthermore it is something you could achieve without it anyway if you would add some braces.
Bottom line: Your code is perfectly fine as it is.

There is no reason to change your implementation. There is no way to do what you want in java 8 with an Optional without having an if, while respecting the idea of not using 'map' for side-effects.
I mean, you could have
public void check(String name) {
Optional<String> nameOpt = Optional.ofNullable(name);
nameOpt.ifPresent(n -> doSomething(n));
if (!nameOpt.isPresent()) {
doMore();
}
}
but that has no sense. here you have a good article what Optional tries to resolve (and hence for what it's meant to be used): mainly for return types. Other stuff is just overusing it.

You can avoid if statement by utilizing Java 8 Optional.map() and Optional.orElseGet() methods. Check following example:
import java.util.Optional;
import java.util.function.Consumer;
final class OptionalTestMain {
public static void main(String[] args) {
check("test", str -> {
System.out.println("Yay, string is not null!");
System.out.println("It's: " + str);
}, () -> {
System.out.println("Crap, string is a null...");
System.out.println("There is nothing for me to do.");
});
check(null, str -> {
System.out.println("Yay, string is not null!");
System.out.println("It's: " + str);
}, () -> {
System.out.println("Crap, string is a null...");
System.out.println("There is nothing for me to do.");
});
}
static void check(String str, Consumer<String> ifPresent, Runnable ifNotPresent) {
Optional.ofNullable(str)
.map(s -> { ifPresent.accept(s); return s; })
.orElseGet(() -> { ifNotPresent.run(); return null; });
}
}
It will produce following output:
Yay, string is not null!
It's: test
Crap, string is a null...
There is nothing for me to do.
Method check expects 3 parameters:
a String (it may be null)
a Consumer lambda expression that does something with this value and does not mutate input value.
a Runnable lambda with no parameters to do something when input String is null.
Of course you could easily modify following method and then utilize the whole potential of Optional class, e.g.:
static String checkAndReturn(String str, Function<String, String> ifPresent, Supplier<String> ifNotPresent) {
return Optional.ofNullable(str)
.map(ifPresent)
.orElseGet(ifNotPresent);
}
Then:
System.out.println(checkAndReturn("test", String::toUpperCase, () -> "no value"));
System.out.println(checkAndReturn(null, String::toUpperCase, () -> "no value"));
will produce following output:
TEST
no value
I hope it helps.

Related

Combining two optionals, cleanest way to write?

Suppose I have:
public void func(){
Optional<Integer> firstRequiredOptional = ...
Optional<Integer> secondRequiredOptional = ...
if(firstRequiredOptional.isPresent() && secondRequiredOptional.isPresent()){
// do something with values of BOTH optionals
}
// Do nothing
}
This function will only execute the if if BOTH the optionals are present.
I am trying to think of a cleaner way (perhaps function ifPresent type) way of writing this, or converting it somehow into Optional<Integer, Integer> with both the ints in one optional if possible?
What is the cleaner way to write this?
Using the if statement is already cleaner than the other alternatives.
alternative 1
You can use ifPresent such as:
firstRequiredOptional.ifPresent(first ->
secondRequiredOptional.ifPresent(second -> something(first, second)));
alternative 2
Use allMatch with Stream in case you don't want to consume the values(not that its not possible) such as:
if (Stream.of(firstRequiredOptional, secondRequiredOptional)
.allMatch(Optional::isPresent)) {
something(); // or something(firstRequiredOptional.get(), secondRequiredOptional.get());
}
Depends on what you mean by "cleaner."
An ifPresent solution, as #Naman points out, looks like:
firstRequiredOptional.ifPresent(firstValue ->
secondRequiredOptional.ifPresent(secondValue -> {
// do something with firstValue, secondValue.
}));
This is "cleaner" in the sense that you don't have to call both .isPresent() and .get() on the two optionals.
There's no Optional<FirstType, SecondType>, but if the combination of these two required values has some kind of meaning, you might want to embody this in a class.
Optional<FullName> fullNameOptional = firstNameOptional.flatMap(firstName ->
secondNameOptional.map(secondName -> new FullName(firstName, secondName));
fullNameOptional.ifPresent(fullName -> {
// do something with fullName.
});
This has the advantage of giving you a single Optional value you can work with, passing to helper methods, etc., and it follows the Command-Query Separation pattern, which tends to have advantages when debugging and breaking your code down into pieces that are simple to unit-test. But it's not "cleaner" in the sense that you're using less code, for example.
If you like the idea of mapping to a single Optional, but don't want to create a type just for this purpose, you can create general-purpose Tuple classes (or use one of several popular Tuple libraries).
Maybe a generic aproach for two Optionals:
import java.util.Optional;
import java.util.function.BiConsumer;
public class OptionalUtils {
public static <T> void ifPresent(Optional<T> optional1, Optional<T> optional2, BiConsumer<T, T> consumer) {
if (optional1.isPresent() && optional2.isPresent()) {
consumer.accept(optional1.get(), optional2.get());
}
}
public static void main(String[] args) {
Optional<Integer> test1 = Optional.of(1);
Optional<Integer> test2 = Optional.of(2);
ifPresent(test1, test2, (a, b) -> {
System.out.println(" a + b =" + (a + b));
});
}
}
Not sure if cleaner, but my intuitive solution is to provide a container and use ofNullable.
This might be something along the lines of:
public class DualOptional<T, K>
{
Optional<T> opt1 = Optional.empty();
Optional<K> opt2 = Optional.empty();
DualOptional( T t, K k )
{
opt1 = Optional.ofNullable( t );
opt2 = Optional.ofNullable( k );
}
public boolean isPresent()
{
return opt1.isPresent() && opt2.isPresent();
}
}
This of course can be expanded to include getters and whatever other functionality is needed.

Java 8 How to return from a method if Optional is not present?

I don't means return a Optional value, I mean for a method:
public void someMethod() {
Optional<Obj> obj = someService.getObj();
if (obj.isPresent()) {
....
} else {
log.info(xxxx);
return;
}
xxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxx
other codes
}
Is is possible to write it with Optional.ifPresent way? I mean, avoid to use the if isPresent thing.
Many thanks.
== updated:
it seems ifPresentOrElse in JDK9 can do this, but is there any way to do this in JAVA8?
I don't need this method return any value, but if the Optional not present, I want to log something.
Seems like a use case for ifPresentOrElse as in Java-9 :
obj.ifPresentOrElse(a -> {...}, () -> {logger.info(xxxx);return; });
If you want to do nothing when the Optional is empty, you can use ifPresent:
public void someMethod() {
someService.getObj().ifPresent (v -> {
....
});
}
Just throwing an idea out there, what about having a method on the service to check if the object is present?
I think that generally you don't want to spread your Optionals all over your code, I'd prefer to keep it inside the service.
On SomeService:
public boolean isObjectPresent() {
return getObj().isPresent();
}
Then
public void someMethod() {
if (someService.isObjectPresent()) {
....
} else {
log.info(xxxx);
return;
}
}
This way you don't have to deal with the Optional in your call as you don't really care about its value
NOTE: Also, I'd add that if you have no code after the if blocks, you don't need the return statement.
Use Optional.ofNullable(input).orElseGet(this::methodName);
If the input is null then it goes to orElseGet logic. If input is not null then return the input value.
Please refer to section 'Difference Between orElse and orElseGet()' of https://www.baeldung.com/java-optional

How to use Java 8 Optionals, performing an action if all three are present?

I have some (simplified) code that uses Java Optionals:
Optional<User> maybeTarget = userRepository.findById(id1);
Optional<String> maybeSourceName = userRepository.findById(id2).map(User::getName);
Optional<String> maybeEventName = eventRepository.findById(id3).map(Event::getName);
maybeTarget.ifPresent(target -> {
maybeSourceName.ifPresent(sourceName -> {
maybeEventName.ifPresent(eventName -> {
sendInvite(target.getEmail(), String.format("Hi %s, $s has invited you to $s", target.getName(), sourceName, meetingName));
}
}
}
Needless to say, this looks and feels bad. But I can't think of another way to do this in a less-nested and more readable way. I considered streaming the 3 Optionals, but discarded the idea as doing a .filter(Optional::isPresent) then a .map(Optional::get) feels even worse.
So is there a better, more 'Java 8' or 'Optional-literate' way of dealing with this situation (essentially multiple Optionals all needed to compute a final operation)?
I think to stream the three Optionals is an overkill, why not the simple
if (maybeTarget.isPresent() && maybeSourceName.isPresent() && maybeEventName.isPresent()) {
...
}
In my eyes, this states the conditional logic more clearly compared to the use of the stream API.
Using a helper function, things at least become un-nested a little:
#FunctionalInterface
interface TriConsumer<T, U, S> {
void accept(T t, U u, S s);
}
public static <T, U, S> void allOf(Optional<T> o1, Optional<U> o2, Optional<S> o3,
TriConsumer<T, U, S> consumer) {
o1.ifPresent(t -> o2.ifPresent(u -> o3.ifPresent(s -> consumer.accept(t, u, s))));
}
allOf(maybeTarget, maybeSourceName, maybeEventName,
(target, sourceName, eventName) -> {
/// ...
});
The obvious downside being that you'd need a separate helper function overload for every different number of Optionals
How about something like this
if(Stream.of(maybeTarget, maybeSourceName,
maybeEventName).allMatch(Optional::isPresent))
{
sendinvite(....)// do get on all optionals.
}
Having said that. If your logic to find in database is only to send mail, then if maybeTarget.ifPresent() is false, then there is no point to fetch the other two values, ain't it?. I am afraid, this kinda logic can be achieved only through traditional if else statements.
Since the original code is being executed for its side effects (sending an email), and not extracting or generating a value, the nested ifPresent calls seem appropriate. The original code doesn't seem too bad, and indeed it seems rather better than some of the answers that have been proposed. However, the statement lambdas and the local variables of type Optional do seem to add a fair amount of clutter.
First, I'll take the liberty of modifying the original code by wrapping it in a method, giving the parameters nice names, and making up some type names. I have no idea if the actual code is like this, but this shouldn't really be surprising to anyone.
// original version, slightly modified
void inviteById(UserId targetId, UserId sourceId, EventId eventId) {
Optional<User> maybeTarget = userRepository.findById(targetId);
Optional<String> maybeSourceName = userRepository.findById(sourceId).map(User::getName);
Optional<String> maybeEventName = eventRepository.findById(eventId).map(Event::getName);
maybeTarget.ifPresent(target -> {
maybeSourceName.ifPresent(sourceName -> {
maybeEventName.ifPresent(eventName -> {
sendInvite(target.getEmail(), String.format("Hi %s, %s has invited you to %s",
target.getName(), sourceName, eventName));
});
});
});
}
I played around with different refactorings, and I found that extracting the inner statement lambda into its own method makes the most sense to me. Given source and target users and an event -- no Optional stuff -- it sends mail about it. This is the computation that needs to be performed after all the optional stuff has been dealt with. I've also moved the data extraction (email, name) in here instead of mixing it with the Optional processing in the outer layer. Again, this makes sense to me: send mail from source to target about event.
void setupInvite(User target, User source, Event event) {
sendInvite(target.getEmail(), String.format("Hi %s, %s has invited you to %s",
target.getName(), source.getName(), event.getName()));
}
Now, let's deal with the optional stuff. As I said above, ifPresent is the way to go here, since we want to do something with side effects. It also provides a way to "extract" the value from an Optional and bind it to a name, but only within the context of a lambda expression. Since we want to do this for three different Optionals, nesting is called for. Nesting allows names from outer lambdas to be captured by inner lambdas. This lets us bind names to values extracted from the Optionals -- but only if they're present. This can't really be done with a linear chain, since some intermediate data structure like a tuple would be necessary to build up the partial results.
Finally, in the innermost lambda, we call the helper method defined above.
void inviteById(UserId targetId, UserId sourceID, EventId eventId) {
userRepository.findById(targetId).ifPresent(
target -> userRepository.findById(sourceID).ifPresent(
source -> eventRepository.findById(eventId).ifPresent(
event -> setupInvite(target, source, event))));
}
Note that I've inlined the Optionals instead of holding them in local variables. This reveals the nesting structure a bit better. It also provides for "short-circuiting" of the operation if one of the lookups doesn't find anything, since ifPresent simply does nothing on an empty Optional.
It's still a bit dense to my eye, though. I think the reason is that this code still depends on some external repositories on which to do the lookups. It's a bit uncomfortable to have this mixed together with the Optional processing. A possibility is simply to extract the lookups into their own methods findUser and findEvent. These are pretty obvious so I won't write them out. But if this were done, the result would be:
void inviteById(UserId targetId, UserId sourceID, EventId eventId) {
findUser(targetId).ifPresent(
target -> findUser(sourceID).ifPresent(
source -> findEvent(eventId).ifPresent(
event -> setupInvite(target, source, event))));
}
Fundamentally, this isn't that different from the original code. It's subjective, but I think I prefer this to the original code. It has the same, fairly simple structure, although nested instead of the typical linear chain of Optional processing. What's different is that the lookups are done conditionally within Optional processing, instead of being done up front, stored in local variables, and then doing only conditional extraction of Optional values. Also, I've separated out data manipulation (extraction of email and name, sending of message) into a separate method. This avoids mixing data manipulation with Optional processing, which I think tends to confuse things if we're dealing with multiple Optional instances.
I think you should consider taking another approach.
I'd start by not issuing the three calls to the DB at the beginning. Instead, I'd issue the 1st query and only if the result is present, I'd issue the 2nd one. I'd then apply the same rationale with regard to the 3rd query and finally, if the last result is also present, I'd send the invite. This would avoid unnecessary calls to the DB when either one of the first two results is not present.
In order to make the code more readable, testable and maintainable, I'd also extract each DB call to its own private method, chaining them with Optional.ifPresent:
public void sendInvite(Long targetId, Long sourceId, Long meetingId) {
userRepository.findById(targetId)
.ifPresent(target -> sendInvite(target, sourceId, meetingId));
}
private void sendInvite(User target, Long sourceId, Long meetingId) {
userRepository.findById(sourceId)
.map(User::getName)
.ifPresent(sourceName -> sendInvite(target, sourceName, meetingId));
}
private void sendInvite(User target, String sourceName, Long meetingId) {
eventRepository.findById(meetingId)
.map(Event::getName)
.ifPresent(meetingName -> sendInvite(target, sourceName, meetingName));
}
private void sendInvite(User target, String sourceName, String meetingName) {
String contents = String.format(
"Hi %s, $s has invited you to $s",
target.getName(),
sourceName,
meetingName);
sendInvite(target.getEmail(), contents);
}
You can use the following if you want to stick to Optional and not commit to consuming the value immediately. It makes use of Triple<L, M, R> from Apache Commons:
/**
* Returns an optional contained a triple if all arguments are present,
* otherwise an absent optional
*/
public static <L, M, R> Optional<Triple<L, M, R>> product(Optional<L> left,
Optional<M> middle, Optional<R> right) {
return left.flatMap(l -> middle.flatMap(m -> right.map(r -> Triple.of(l, m, r))));
}
// Used as
product(maybeTarget, maybeSourceName, maybeEventName).ifPresent(this::sendInvite);
One could imagine a similar approach for two, or multiple Optionals, although java unfortunately doesn't have a general tuple type (yet).
The first approach is not perfect (it does not support laziness - all 3 database calls will be triggered anyway):
Optional<User> target = userRepository.findById(id1);
Optional<String> sourceName = userRepository.findById(id2).map(User::getName);
Optional<String> eventName = eventRepository.findById(id3).map(Event::getName);
if (Stream.of(target, sourceName, eventName).anyMatch(obj -> !obj.isPresent())) {
return;
}
sendInvite(target.get(), sourceName.get(), eventName.get());
The following example is a little bit verbose, but it supports laziness and readability:
private void sendIfValid() {
Optional<User> target = userRepository.findById(id1);
if (!target.isPresent()) {
return;
}
Optional<String> sourceName = userRepository.findById(id2).map(User::getName);
if (!sourceName.isPresent()) {
return;
}
Optional<String> eventName = eventRepository.findById(id3).map(Event::getName);
if (!eventName.isPresent()) {
return;
}
sendInvite(target.get(), sourceName.get(), eventName.get());
}
private void sendInvite(User target, String sourceName, String eventName) {
// ...
}
Well I took the same approach of Federico to only call the DB when needed, it's quite verbose too, but lazy. I also simplified this a bit. Considering you have these 3 methods:
public static Optional<String> firstCall() {
System.out.println("first call");
return Optional.of("first");
}
public static Optional<String> secondCall() {
System.out.println("second call");
return Optional.empty();
}
public static Optional<String> thirdCall() {
System.out.println("third call");
return Optional.empty();
}
I've implemented it like this:
firstCall()
.flatMap(x -> secondCall().map(y -> Stream.of(x, y))
.flatMap(z -> thirdCall().map(n -> Stream.concat(z, Stream.of(n)))))
.ifPresent(st -> System.out.println(st.collect(Collectors.joining("|"))));
You can create an infrastructure to handle a variable amount of inputs. For this to be a good design though, your inputs should not be Optional<?>; but Supplier<Optional<?>> so you can short-circuit the unnecessary evaluation of Optionals while trying to determine whether or not all are present.
Because of this, it'd be better to create a utility wrapper around your Optionals that provides transparent access to the evaluated value using a singleton pattern, like the following:
class OptionalSupplier {
private final Supplier<Optional<?>> optionalSupplier;
private Optional<?> evaluatedOptional = null;
public OptionalSupplier(Supplier<Optional<?>> supplier) {
this.optionalSupplier = supplier;
}
public Optional<?> getEvaluatedOptional() {
if (evaluatedOptional == null)
evaluatedOptional = optionalSupplier.get();
return evaluatedOptional;
}
}
Then you can create another class that handles a List of these wrappers and provides a programmatic API to execute a Function that takes as parameters the evaluated values of the actual optionals, hiding further the users involvement in the process. You can overload the method to execute a Consumer with the same parameters. Such class would look something like this:
class OptionalSemaphores {
private List<OptionalSupplier> optionalSuppliers;
private List<Object> results = null;
private boolean allPresent;
public OptionalSemaphores(Supplier<Optional<?>>... suppliers) {
optionalSuppliers = Stream.of(suppliers)
.map(OptionalSupplier::new)
.collect(Collectors.toList());
allPresent = optionalSuppliers.stream()
.map(OptionalSupplier::getEvaluatedOptional)
.allMatch(Optional::isPresent);
if (allPresent)
results = optionalSuppliers.stream()
.map(OptionalSupplier::getEvaluatedOptional)
.map(Optional::get)
.collect(Collectors.toList());
}
public boolean isAllPresent() {
return allPresent;
}
public <T> T execute(Function<List<Object>, T> function, T defaultValue) {
return (allPresent) ? function.apply(results) : defaultValue;
}
public void execute(Consumer<List<Object>> function) {
if (allPresent)
function.accept(results);
}
}
Finally all you have left to do is to create objects of this class (OptionalSemaphores) using Suppliers of your Optionals (Supplier<Optional<?>>) and invoking any of the overloaded execute methods to run (IF all Optionals are present) with a List containing the corresponding evaluated values from your Optionals. The following is a full working demo of this:
public class OptionalsTester {
public static void main(String[] args) {
Supplier<Optional<?>> s1 = () -> Optional.of("Hello");
Supplier<Optional<?>> s2 = () -> Optional.of(1L);
Supplier<Optional<?>> s3 = () -> Optional.of(55.87);
Supplier<Optional<?>> s4 = () -> Optional.of(true);
Supplier<Optional<?>> s5 = () -> Optional.of("World");
Supplier<Optional<?>> failure = () -> Optional.ofNullable(null);
Supplier<Optional<?>> s7 = () -> Optional.of(55);
System.out.print("\nFAILING SEMAPHORES: ");
new OptionalSemaphores(s1, s2, s3, s4, s5, failure, s7).execute(System.out::println);
System.out.print("\nSUCCESSFUL SEMAPHORES: ");
new OptionalSemaphores(s1, s2, s3, s4, s5, s7).execute(System.out::println);
}
static class OptionalSemaphores {
private List<OptionalSupplier> optionalSuppliers;
private List<Object> results = null;
private boolean allPresent;
public OptionalSemaphores(Supplier<Optional<?>>... suppliers) {
optionalSuppliers = Stream.of(suppliers)
.map(OptionalSupplier::new)
.collect(Collectors.toList());
allPresent = optionalSuppliers.stream()
.map(OptionalSupplier::getEvaluatedOptional)
.allMatch(Optional::isPresent);
if (allPresent)
results = optionalSuppliers.stream()
.map(OptionalSupplier::getEvaluatedOptional)
.map(Optional::get)
.collect(Collectors.toList());
}
public boolean isAllPresent() {
return allPresent;
}
public <T> T execute(Function<List<Object>, T> function, T defaultValue) {
return (allPresent) ? function.apply(results) : defaultValue;
}
public void execute(Consumer<List<Object>> function) {
if (allPresent)
function.accept(results);
}
}
static class OptionalSupplier {
private final Supplier<Optional<?>> optionalSupplier;
private Optional<?> evaluatedOptional = null;
public OptionalSupplier(Supplier<Optional<?>> supplier) {
this.optionalSupplier = supplier;
}
public Optional<?> getEvaluatedOptional() {
if (evaluatedOptional == null)
evaluatedOptional = optionalSupplier.get();
return evaluatedOptional;
}
}
}
Complete code on GitHub
Hope this helps.
If you treat Optional just as a marker for method return values, the code becomes very simple:
User target = userRepository.findById(id1).orElse(null);
User source = userRepository.findById(id2).orElse(null);
Event event = eventRepository.findById(id3).orElse(null);
if (target != null && source != null && event != null) {
String message = String.format("Hi %s, %s has invited you to %s",
target.getName(), source.getName(), event.getName());
sendInvite(target.getEmail(), message);
}
The point of Optional is not that you must use it everywhere. Instead, it serves as a marker for method return values to inform the caller to check for absentness. In this case, the orElse(null) takes care of this, and the calling code is fully concious about the possible nullness.
return userRepository.findById(id)
.flatMap(target -> userRepository.findById(id2)
.map(User::getName)
.flatMap(sourceName -> eventRepository.findById(id3)
.map(Event::getName)
.map(eventName-> createInvite(target, sourceName, eventName))))
First of all you return an Optional as well. It's better to have a method first that creates an invite, which you can call and then send if it's not empty.
Among other things, it's easier to test. Using flatMap you also get the benefit of laziness, since if the first result is empty, nothing else will be evaluated.
When you want to use multiple optionals, you always should use a combination of map and flatMap.
I'm also not using target.getEmail() and target.getName(), those should be safely extracted in createInvite method, since I don't know if they can be nulls or not.
Keeping in mind that Exceptions should not be used in this fashion,
for conciseness you can consider as well:
try {
doSomething( optional1.get(), optional2.get(), optional3.get() );
} catch( NoSuchElementException e ) {
// report, log, do nothing
}
Remember, you can define Classes and Records inline to keep the state explicit and flattened vs. nested using callbacks/closures. It might seem a bit overkill for a small example like this, but it really helps when each nested 'chain' ends up doing work.
For example, given your 3 Optionals using lombok:
#Value #With class Temp {User target; String source; String eventName;}
maybeTarget
.map(target -> new Temp(target, null, null))
.flatMap(tmp -> maybeSourceName.map(tmp::withSource))
.flatMap(tmp -> maybeEventName.map(tmp::withEventName))
.ifPresent(tmp -> System.out.printf("Hi %s, %s has invited you to %s%n", tmp.target.getName(), tmp.source, tmp.eventName));
You can do the same w/records but you'll have to do a bit more work since you have to copy everything by hand:
record TempRecord(User target, String source, String eventName) {}
maybeTarget
.map(target -> new TempRecord(target, null, null))
.flatMap(tmp -> maybeSourceName.map(source -> new TempRecord(tmp.target, source, null)))
.flatMap(tmp -> maybeEventName.map(eventName -> new TempRecord(tmp.target, tmp.source, eventName)))
.ifPresent(tmp -> System.out.printf("Hi %s, %s has invited you to %s%n", tmp.target.getName(), tmp.source, tmp.eventName));
I've tried to keep the data immutable and functions pure.

Clean java programming, is it a bad idea to use lambdas to generate method input parameters?

Just a quick question regarding good programming practices,
Performance aside, how much of a good/bad idea could something like this be?
I am oversimplifying the problem to get my point across, but is something like this totally wrong?
public void methodWithInputString(String data) {
// do something with data
}
public void methodThatCallsTheAbove() {
methodWithInputString(
// lambda with no input and a string as output
(() -> {
if (this.conditionIsTrue)
return "Condition is true";
else
return "Condition is false";
}).apply();
);
}
The alternative would simply be:
public void methodThatCallsTheAbove() {
if (this.conditionIsTrue)
methodWithInputString("Condition is true");
else
methodWithInputString("Condition is false");
}
I understand that the second is the obvious/correct approach but in a situation where using the first one makes my code cleaner is it still a nonsensical thing to do?
+1 for Andy Turner remark.
Plus: Avoid object properties reference inside your lambda.
I guess a compilable version of what you are trying to show would be like this:
public class Demo {
private static final Function<Boolean, String> GET_STRING_DEPENDING_ON_BOOLEAN = flagValue -> "Condition is ".concat(String.valueOf(flagValue));
private boolean conditionIsTrue;
public void methodWithInputString(final String data) {
// do something with data
}
public void methodThatCallsTheAbove() {
methodWithInputString(GET_STRING_DEPENDING_ON_BOOLEAN.apply(this.conditionIsTrue));
}
}
The only advantage of doing this (using a lambda instead of a method) is to be able to re use this lambda and chaining something else with.
Example:
methodWithInputString(GET_STRING_DEPENDING_ON_BOOLEAN.andThen(data -> data.concat("somethingelse")).apply(this.conditionIsTrue));

Break or return from Java 8 stream forEach?

When using external iteration over an Iterable we use break or return from enhanced for-each loop as:
for (SomeObject obj : someObjects) {
if (some_condition_met) {
break; // or return obj
}
}
How can we break or return using the internal iteration in a Java 8 lambda expression like:
someObjects.forEach(obj -> {
//what to do here?
})
If you need this, you shouldn't use forEach, but one of the other methods available on streams; which one, depends on what your goal is.
For example, if the goal of this loop is to find the first element which matches some predicate:
Optional<SomeObject> result =
someObjects.stream().filter(obj -> some_condition_met).findFirst();
(Note: This will not iterate the whole collection, because streams are lazily evaluated - it will stop at the first object that matches the condition).
If you just want to know if there's an element in the collection for which the condition is true, you could use anyMatch:
boolean result = someObjects.stream().anyMatch(obj -> some_condition_met);
A return in a lambda equals a continue in a for-each, but there is no equivalent to a break. You can just do a return to continue:
someObjects.forEach(obj -> {
if (some_condition_met) {
return;
}
})
This is possible for Iterable.forEach() (but not reliably with Stream.forEach()). The solution is not nice, but it is possible.
WARNING: You should not use it for controlling business logic, but purely for handling an exceptional situation which occurs during the execution of the forEach(). Such as a resource suddenly stops being accessible, one of the processed objects is violating a contract (e.g. contract says that all the elements in the stream must not be null but suddenly and unexpectedly one of them is null) etc.
According to the documentation for Iterable.forEach():
Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception... Exceptions thrown by the action are relayed to the caller.
So you throw an exception which will immediately break the internal loop.
The code will be something like this - I cannot say I like it but it works. You create your own class BreakException which extends RuntimeException.
try {
someObjects.forEach(obj -> {
// some useful code here
if(some_exceptional_condition_met) {
throw new BreakException();
}
}
}
catch (BreakException e) {
// here you know that your condition has been met at least once
}
Notice that the try...catch is not around the lambda expression, but rather around the whole forEach() method. To make it more visible, see the following transcription of the code which shows it more clearly:
Consumer<? super SomeObject> action = obj -> {
// some useful code here
if(some_exceptional_condition_met) {
throw new BreakException();
}
});
try {
someObjects.forEach(action);
}
catch (BreakException e) {
// here you know that your condition has been met at least once
}
Below you find the solution I used in a project. Instead forEach just use allMatch:
someObjects.allMatch(obj -> {
return !some_condition_met;
});
Update with Java 9+ with takeWhile:
MutableBoolean ongoing = MutableBoolean.of(true);
someobjects.stream()...takeWhile(t -> ongoing.value()).forEach(t -> {
// doing something.
if (...) { // want to break;
ongoing.setFalse();
}
});
Either you need to use a method which uses a predicate indicating whether to keep going (so it has the break instead) or you need to throw an exception - which is a very ugly approach, of course.
So you could write a forEachConditional method like this:
public static <T> void forEachConditional(Iterable<T> source,
Predicate<T> action) {
for (T item : source) {
if (!action.test(item)) {
break;
}
}
}
Rather than Predicate<T>, you might want to define your own functional interface with the same general method (something taking a T and returning a bool) but with names that indicate the expectation more clearly - Predicate<T> isn't ideal here.
You can use java8 + rxjava.
//import java.util.stream.IntStream;
//import rx.Observable;
IntStream intStream = IntStream.range(1,10000000);
Observable.from(() -> intStream.iterator())
.takeWhile(n -> n < 10)
.forEach(n-> System.out.println(n));
For maximal performance in parallel operations use findAny() which is similar to findFirst().
Optional<SomeObject> result =
someObjects.stream().filter(obj -> some_condition_met).findAny();
However If a stable result is desired, use findFirst() instead.
Also note that matching patterns (anyMatch()/allMatch) will return only boolean, you will not get matched object.
I have achieved by something like this
private void doSomething() {
List<Action> actions = actionRepository.findAll();
boolean actionHasFormFields = actions.stream().anyMatch(actionHasMyFieldsPredicate());
if (actionHasFormFields){
context.addError(someError);
}
}
}
private Predicate<Action> actionHasMyFieldsPredicate(){
return action -> action.getMyField1() != null;
}
You can achieve that using a mix of peek(..) and anyMatch(..).
Using your example:
someObjects.stream().peek(obj -> {
<your code here>
}).anyMatch(obj -> !<some_condition_met>);
Or just write a generic util method:
public static <T> void streamWhile(Stream<T> stream, Predicate<? super T> predicate, Consumer<? super T> consumer) {
stream.peek(consumer).anyMatch(predicate.negate());
}
And then use it, like this:
streamWhile(someObjects.stream(), obj -> <some_condition_met>, obj -> {
<your code here>
});
int valueToMatch = 7;
Stream.of(1,2,3,4,5,6,7,8).anyMatch(val->{
boolean isMatch = val == valueToMatch;
if(isMatch) {
/*Do whatever you want...*/
System.out.println(val);
}
return isMatch;
});
It will do only operation where it find match, and after find match it stop it's iteration.
public static void main(String[] args) {
List<String> list = Arrays.asList("one", "two", "three", "seven", "nine");
AtomicBoolean yes = new AtomicBoolean(true);
list.stream().takeWhile(value -> yes.get()).forEach(value -> {
System.out.println("prior cond" + value);
if (value.equals("two")) {
System.out.println(value);
yes.set(false);
}
});
//System.out.println("Hello World");
}
What about this one:
final BooleanWrapper condition = new BooleanWrapper();
someObjects.forEach(obj -> {
if (condition.ok()) {
// YOUR CODE to control
condition.stop();
}
});
Where BooleanWrapper is a class you must implement to control the flow.
I would suggest using anyMatch. Example:-
return someObjects.stream().anyMatch(obj ->
some_condition_met;
);
You can refer this post for understanding anyMatch:-
https://beginnersbook.com/2017/11/java-8-stream-anymatch-example/

Categories