6

Can someone help me with the below piece of code? I would like an equivalent using Optional functions.

public String getMyRequiredValue(Optional<String> value) {
    if(value.isPresent()) {
        Optional<String> optionVal = getAnotherValue(value.get());
        if(optionVal.isPresent()) {
            return optionVal.get();
        } else {
            return null;
        }
    } else {
        return "Random";
    }
}

public Optional<String> getAnotherValue(String value) { ... }

Just a note I tried this, but it does not work

return value.map(lang -> getAnotherValue(lang).orElse(null)).orElse("Random");

The thing that is not working is - when the value is present and getAnotherValue returns Optional.empty() I want the original function to return null. It is returning "Random" right now.

My assumption is since the map method returns null it gets replaced by "Random".

Note that the original code was written by someone else. Since, it has a lot of dependencies, I cannot change the input/output parameters. :(

0

1 Answer 1

6

The solution originally suggested by @Andreas in the comments:

public String getMyRequiredValue(Optional<String> value) {
    return value.isPresent() ? getAnotherValue(value.get()).orElse(null) : "Random";
}

The solution I came up with first. It breaks the rule that suggests we always need to check isPresent() before calling get() and introduces exception handling. So it's better to stick to the first idea.

public String getMyRequiredValue2(Optional<String> value) {
    try {
        return getAnotherValue(value.get()).orElse(null);
    } catch (NoSuchElementException e) {
        return "Random";
    }
}

I've seen you were trying to utilise map and flatMap. If they result in an Optional.empty(), it's unclear where null came from: it could be either value or getAnotherValue(value.get()).

We could track that by saving the value coming from value.get() into a Holder<String>:

public String getMyRequiredValue3(Optional<String> value) {
    final Holder<String> holder = new Holder<>();
    return value.flatMap(i -> getAnotherValue(holder.value = i))
                .orElse(holder.value == null ? "Random" : null);
}

Again, the first approach still beats this.


EDIT: As pointed out by @Holder, we don't need a Holder from the preceding example. Instead we can check value.isPresent():

public String getMyRequiredValue4(Optional<String> value) {
    return value.flatMap(this::getAnotherValue) 
                .orElse(value.isPresent() ? null : "Random");
}
Sign up to request clarification or add additional context in comments.

3 Comments

Using exceptions for control flow is an anti-pattern. I think you shouldn't even mention that option in yor answer, or at least make it much more clear that it is not a good idea.
You don’t need that Holder object, when you already have the Optional<String> value doing exactly that, i.e. containing the same value or being empty. So you can simply use return value.flatMap(i -> getAnotherValue(holder.value = i)) .orElse(value.isPresent()? null: "Random");
Of course, also without the holder.value = part; leftover from copy&paste…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.