Is there a more elegant way to represent the following algorithm using the Java core API?
Optional<Float> input = Optional.of(A);
Optional<Float> output = input.map(function1).map(function2);
if (!output.isPresent())
{
output = input.map(function1).map(function2);
if (!output.isPresent())
{
output = input.map(function3).map(function4);
if (!output.isPresent())
output = input.map(function5).map(function6);
}
}
That is, instead of nesting multiple invocations of isPresent()
I'd like to invoke a method like map()
but that would only get invoked if a value is absent.
In an ideal world, I want to invoke something along the lines of:
Optional<Float> output = input.or(input.map(function1).map(function2), input.map(function2).map(function3), input.map(function4).map(function5));
This is what I've got so far, but can we do better?
public class Optionals
{
/**
* @param <T> the type of value returned by the Optionals
* @param suppliers one or more suppliers that return a supplier
* @return the first Optional that {@link Optional#isPresent() isPresent()}
*/
public static <T> Optional<T> or(Supplier<Optional<T>>... suppliers)
{
for (Supplier<Optional<T>> supplier: suppliers)
{
Optional<T> candidate = supplier.get();
if (candidate.isPresent())
return candidate;
}
return Optional.empty();
}
/**
* Prevent construction.
*/
private Optionals()
{
}
}
I don't like the Supplier
scheme to much in this case and would probably prefer this approach:
public static void main(String[] args) {
Float x = 1.0f;
final Optional<Float> input = Optional.of(x);
Optional<Float> output = firstPresent(input, (a) -> a.map(FUNCTION1).map(FUNCTION2),
(a) -> a.map(FUNCTION3).map(FUNCTION4),
(a) -> a.map(FUNCTION5).map(FUNCTION6));
}
@SafeVarargs
public static <I,O> Optional<O> firstPresent(Optional<I> input, Function<Optional<I>, Optional<O>>... functions) {
for (Function<Optional<I>, Optional<O>> function : functions) {
final Optional<O> output = function.apply(input);
if(output.isPresent()) {
return output;
}
}
return Optional.empty();
}