As per your requirements, you don't need a Map<String, Integer>, but a Map<String, List<Integer>> instead. In other words, you're after a multimap.
One way to achieve such data structure in Java 8+, is by using the Map.computeIfAbsent and Map.computeIfPresent methods for insertions and removals, respectively:
Map<String, List<Integer>> map = new HashMap<>(); // use diamond operator
// INSERT
map.computeIfAbsent("A", k -> new ArrayList<>()).add(1);
map.computeIfAbsent("A", k -> new ArrayList<>()).add(2);
map.computeIfAbsent("A", k -> new ArrayList<>()).add(3);
map.computeIfAbsent("B", k -> new ArrayList<>()).add(4);
// REMOVE
map.computeIfPresent("A", (k, v) -> {
v.remove(1);
return v.isEmpty() ? null : v;
});
map.computeIfPresent("A", (k, v) -> {
v.remove(2);
return v.isEmpty() ? null : v;
});
map.computeIfPresent("A", (k, v) -> {
v.remove(3);
return v.isEmpty() ? null : v;
});
map.computeIfPresent("B", (k, v) -> {
v.remove(4);
return v.isEmpty() ? null : v;
});
EDIT:
The remapping function argument for the removals could be extarcted out to the following utility method:
static <K, V> BiFunction<K, List<V>> removing(V elem) {
return (k, v) -> { v.remove(elem); return v.isEmpty() ? null : v; };
}
Which could then be used as follows:
map.computeIfPresent("A", removing(1));
map.computeIfPresent("A", removing(2));
map.computeIfPresent("A", removing(3));
map.computeIfPresent("B", removing(4));
HashMap<String, Set<Integer>>