I need a map that can hold null values and can return Optional wrapped value.
- I know
HashMap
can have null values, but it will not make it apparent to caller that value can be null. - The easiest alternative is to use
Map<K, Optional<V>>
, but usingOptional
for data type is not ideal. (Relevant SO post about usingOptional
only for return: Use of Optional in a map) - I couldn't extend
HashMap
class very well with itsentrySet()
method still facing the same null value issue, so I wrote my class that wrapsHashMap
and hasget()
and customEntry.getValue()
that returnsOptional
wrapped value. (still figuring out how to write a version ofCollectors.toMap
for this class) - The problem now is the class is not easily "replaceable" with
Map
(not programming to interface) and a custom-not-much-extensible-map is circulating in my business logic that I am slightly uncomfortable with.
public class CustomMap<K, V> {
private final Map<K, V> map;
public CustomMap() {
map = new HashMap<>();
}
public Optional<V> get(@NonNull final K k) { // Lombok.NonNull
return Optional.ofNullable(map.get(k));
}
public void put(@NonNull final K k, @Nullable final V v) {
map.put(k, v);
}
public Set<Entry<K, V>> entrySet() {
return map.entrySet().stream()
.map(e -> new Entry(e.getKey(), e.getValue()))
.collect(toImmutableSet());
}
public Set<K> keySet() {
return map.keySet();
}
public static class Entry<K, V> {
private final K k;
private final V v;
public Entry(K k, V v) {
this.k = k;
this.v = v;
}
public K getKey() {
return k;
}
public Optional<V> getValue() {
return Optional.ofNullable(v);
}
}
}
Expectation: customMap.get(K)
should return Optional
wrapped object and customMap.put(K, V)
should not need to take Optional<V>
as input. CustomMap
should be able to act as Map
.
There should be cleaner and extensible way to achieve this and I feel I am missing something obvious. Any suggestions?