I have a Map<String, List<String>>
in my code, where I'd avoid potential null pointers if the map's #get()
method returned an empty list instead of null. Is there anything like this in the java API? Should I just extend HashMap
?

- 35,493
- 19
- 190
- 259

- 7,572
- 2
- 25
- 22
-
8using the decorator pattern would probably be better than extending HashMap... – kem Jan 28 '11 at 21:50
-
1I don't doubt you, but why would it be better? – jk. Jan 28 '11 at 21:52
-
7@jk: Why would you want to limit yourself to it *always* being a HashMap? What if sometimes you wanted a LinkedHashMap? Or a ConcurrentHashMap? Or a TreeMap? Basically, favour composition over inheritance :) – Jon Skeet Jan 28 '11 at 21:54
-
@Jon & @kem, I'm not too familiar with the decorator panel, as the examples are typically for GUI design, which I don't do. I'm guessing by @Jon's statement that a decorator will avoid binding to a particular implementation? – jk. Jan 28 '11 at 21:57
-
@jk: Yes. See my answer for a bit more detail. – Jon Skeet Jan 28 '11 at 21:58
-
Okay, I've researched and understand the decorator pattern now. Thanks. You should put this answer below so I can give credit! – jk. Jan 28 '11 at 22:04
-
@jk: @Jon's answer is an example of the decorator pattern. – Mark Peters Jan 28 '11 at 22:13
-
1@jk: I strongly recommend using a Guava `Multimap` as suggested by @Stephen C. I think this is what you really want, rather than a general purpose `Map` that returns a non-null value when it doesn't contain a key. – ColinD Jan 29 '11 at 02:07
-
https://groups.google.com/forum/?fromgroups#!topic/guava-discuss/eVRHDBcgynA%5B1-25%5D – Paweł Prażak Aug 20 '12 at 08:44
-
2This is a duplicate of http://stackoverflow.com/questions/7519339/hashmap-to-return-default-value-for-non-found-keys – Mark Butler Dec 24 '12 at 08:58
6 Answers
Thanks to default
methods, Java 8 now has this built in with Map::getOrDefault
:
Map<Integer, String> map = ...
map.put(1, "1");
System.out.println(map.getOrDefault(1, "2")); // "1"
System.out.println(map.getOrDefault(2, "2")); // "2"

- 44,417
- 8
- 90
- 141
-
2This is the slimmest answer as it doesn't require Guava. And, by the way, it was what I was looking for. Upvoting. – Laurent Caillette Feb 24 '15 at 21:44
-
2Looks like based on timing this is the best solution, but came way late to the party (thanks java 8!). I like its simplicity. +1 – D. Ben Knoble Oct 13 '15 at 02:02
-
Should be the accepted answer now that Java 8 is commonplace. – Cypress Frankenfeld May 03 '18 at 17:53
-
This is useful, but actually the OP asked for the map's `#get` method to return the value, not use another method. These things are not the same =) – vadipp May 26 '21 at 10:18
-
This does not respond the original question - the OP wants to "avoid potential null pointers". The implementation of `getOrDefault` is more or less like `if (get(key) != null) || containsKey(key)) return get(key) else return defaultValue;`. So if the map contains the key, but the value is `null`, you will not avoid the null pointer! – Honza Zidek Nov 20 '21 at 01:23
@Jon's answer is a good way to do what you are asking directly.
But is strikes me that what you might be trying to implement is a "multimap"; i.e. a mapping from a key to a collection of values. If that is the case, then you should also look at the multimap classes in Guava or Apache commons collections.
Look at:
- the
com.google.common.collect.Multimap
interface and its implementations, or - the
org.apache.commons.collections.MultiMap
interface and its implementations. - the
org.apache.commons.collections4.MultiMap
interface and its implementations (a new version of the previous MultiMap; introduced in v4).

- 698,415
- 94
- 811
- 1,216
-
4+1 And `get()` on a `Multimap` that doesn't contain the key returns an empty `Collection` by contract... exactly what the OP wants. The same isn't true of the Apache Commons `MultiMap` which has unspecified behavior. – ColinD Jan 29 '11 at 02:05
-
2@ColinD True. When using apache commons, we can use DefaultedMap, which returns a default value when the map does not contain the specified value. – simao May 09 '11 at 11:28
As noted in comments:
Guava's computing map concept was superseded with
LoadingCache
. Also java 8 introduced to Map interface nicecomputeIfAbsent
default method which doesn't break map contract and features lazy evaluation .
Guava had the idea of a "computing map" which will execute a function to provide a value if it's not present. It was implemented in MapMaker.makeComputingMap
; you could now use CacheBuilder
- see CacheBuilder.build
for more details.
It may be overkill for what you're after - you might be better off just writing a Map
implementation which has a Map
(using composition rather than extending any particular implementation) and then just return the default if it's not present. Every method other than get
could probably just delegate to the other map:
public class DefaultingMap<K, V> implements Map<K, V>
{
private final Map<K, V> map;
private final V defaultValue;
public DefaultingMap(Map<K, V> map, V defaultValue)
{
this.map = map;
this.defaultValue = defaultValue;
}
@Override public V get(Object key)
{
V ret = map.get(key);
if (ret == null)
{
ret = defaultValue;
}
return ret;
}
@Override public int size()
{
return map.size();
}
// etc
}

- 1,421,763
- 867
- 9,128
- 9,194
-
5Beware: doing only this breaks the contract for `get()`: that if the map doesn't contain the key, `null` is returned. To be conformant you should override `containsKey()` to *always* return `true`. I would assume `makeComputingMap()` would do that as well but didn't find it stated explicitly in the docs. – Mark Peters Jan 28 '11 at 22:08
-
3@Mark: Possibly. Although then you get into trickiness around iterating over the keys, as well... basically sooner or later the abstraction breaks. *Where* you break it would definitely be a matter for deep consideration :) – Jon Skeet Jan 28 '11 at 22:09
-
2The `// etc` is not small, and makes this solution impractical IMO. – kevin cline Nov 09 '12 at 19:11
-
4Alternately you could extend com.google.common.collect.ForwardingMap (from Google Guava) which makes the implementation @JonSkeet suggested much less verbose. – Spina Nov 19 '12 at 17:37
-
2Guava's computing map concept was superseded with [LoadingCache](https://code.google.com/p/guava-libraries/wiki/CachesExplained). Also java 8 introduced to Map interface nice [computeIfAbsent](http://stackoverflow.com/a/31234010/603516) default method which doesn't break map contract and features lazy evaluation – Vadzim Jul 05 '15 at 19:17
-
-
The link to Guava's `MapMaker.makeComputingMap` is dead – naXa stands with Ukraine Apr 12 '17 at 13:57
-
1@naXa: Yes, for reasons that the start of the answer explains. I've updated the links a bit more though. – Jon Skeet Apr 12 '17 at 15:35
Similar to previous posts except you can just override the get method if you want to change its behaviour.
Map<String, List<String>> map = new LinkedHashMap<String, List<String>>() {
public String get(Object key) {
List<String> list = super.get(key);
if (list == null && key instanceof String)
super.put(key, list = new ArrayList<String>());
return list;
}
};

- 525,659
- 79
- 751
- 1,130
Guava has a method to do exactly what you want. It is similar to Argote's answer.
Map<String, List<String>> myMap = ...
Functions.forMap(myMap, Arrays.asList("default", "value"));

- 1
- 1

- 30,998
- 16
- 147
- 256
-
-
2Maybe I'm missing something, but how does this create a `Map` implementation that has a default value? – ach Aug 04 '14 at 15:00
-
1It doesn't. It creates a Guava `Function`, which is similar to a `Map`. The `Map` interface doesn't allow for default values. – Heath Borders Aug 04 '14 at 15:04
-
Ok, I thought that there was a leap of logic somewhere that I wasn't getting. The OP is asking specifically for an implementation of `Map`, and you say that this does "exactly what you want". – ach Aug 04 '14 at 16:32
-
2What the OP wants breaks `Map`'s contract, so the OP wants something that isn't a `Map`. :) – Heath Borders Aug 04 '14 at 16:43
It seems to me that you can simply write a wrapper function to get the value you want and if it's null
return the default instead.
Map<String, List<String>> myMap = new Map<String, List<String>>();
public List<String> myGet(String key) {
List<String> ret = myMap.get(key);
if(ret == NULL) {
return defaultList(); // where defaultList is a function that generates your default list.
}
return ret;
}
This assumes that your myMap
is a global variable (for simplicity's sake), if that's not what you want then you can also extend Map
or HashMap
into something like MyMap
and just include this extra function. That way you can use it from any place where a MyMap
object is instantiated.

- 2,155
- 1
- 15
- 20
-
2This doesn't help much if you need to pass the map to something expecting a Map. – Jon Skeet Jan 28 '11 at 22:01