On various projects I worked on, I found a pattern like
Map<Integer, List<String>> listMap = new HashMap<Integer, List<String>>();
public void addValue(Integer key, String value) {
if (!listMap.containsKey(key)) {
listMap.put(key, new ArrayList<String>());
}
listMap.get(key).add(value);
}
to populate Maps that have Lists
as values.
As this is such a common pattern I wondered if there isn't some convencience class in the standard libraries or something like guava that manages adding and removing values to that structure.
Guava offers Multimap
, which is very suited for your purpose:
ListMultimap<Integer, String> listMap = ArrayListMultimap.create();
public void addValue(Integer key, String value) {
listMap.put(key, value);
}
public List<String> getValues(Integer key) {
return listMap.get(key);
}
public Map<Integer, List<String>> asMap() {
// See documentation for details
return Multimaps.asMap(listMap);
}
Java 8 also offers a more convenient way of getting and initializing a value in a single statement:
Map<Integer, List<String>> listMap = new HashMap<>();
public void addValue(Integer key, String value) {
listMap.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
}
On a side note, I would modify your original example a bit to avoid an extra lookup when a matching key is found:
public void addValue(Integer key, String value) {
List<String> values = listMap.get(key);
if (values == null) {
listMap.put(key, values = new ArrayList<>());
}
values.add(value);
}