2

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?

jjot0
  • 209
  • 2
  • 6

4 Answers4

4

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()); 
}
Community
  • 1
  • 1
Naman
  • 27,789
  • 26
  • 218
  • 353
0

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

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
0

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

    }
}
Turo
  • 4,724
  • 2
  • 14
  • 27
0

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.

Koenigsberg
  • 1,726
  • 1
  • 10
  • 22