I have a nullable Map<String, String> myMap
in my Java 8 class.
I need to fetch a value from the map based on the following condition.
- get keyA;
- if not present, get keyB;
- if not present, get keyC.
I understand that Java 8's Optional<T>
brings the required behavior. Is there a way to use Optional
to elegantly get the data instead of using containsKey
checks?
CodePudding user response:
Building on Alexander Ivanchenko's answer, you could get the first non-null value from the map based on a series of alternate keys:
public static Optional<String> getValue(Map<String, String> map,
String keyA, String... keys) {
Optional<String> result = Optional.ofNullable(map.get(keyA));
for (String key : keys) {
if (result.isPresent()) break;
result = result.or(() -> Optional.ofNullable(map.get(key)));
}
return result;
}
You could use the getOrDefault
method of map, but something like
map.getOrDefault("keyA", map.getOrDefault("keyB", map.get("keyC")))
seems overly specific and complicated, and you still have to deal with the fact that neither keyA nor keyB nor keyC might be present, so you might still get null
, and this has the performance penalty of looking up all three values from the map no matter which is returned.
It also only works for three keys.
CodePudding user response:
No. There is no special integration of Optional with Maps.
More to the point, Optional
does not support null values. Assuming that by "nullable map" you mean "a map that can contain null values", you can't possibly use Optional
to distinguish between "null values that are in your map" and "values that aren't in your map at all." There is absolutely no way to use Optional
helpfully in this scenario.
CodePudding user response:
You can get an Optional
result of retrieving the value corresponding to one of the given keys from a Map
containing nullable values by using Stream.ofNullable()
and Optional.or()
.
Method Optional.or()
expects a supplier of Optional
which will be utilized only if this method was invoked on an empty optional.
public static Optional<String> getValue(Map<String, String> myMap,
String keyA, String keyB, String keyC) {
return Stream.ofNullable(myMap) // precaution for myMap == null
.flatMap(map -> Stream.ofNullable(map.get(keyA)))
.findFirst()
.or(() -> Optional.ofNullable(myMap.get(keyB))) // evaluated only if keyA is not present
.or(() -> Optional.ofNullable(myMap.get(keyC))); // evaluated only if both keyA and keyB are not present
}