Optional<String> map function returns null

meso :

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. :(

Andrew Tobilko :

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=78227&siteId=1