I've been looking at the problem of writing a concurrent Multimap, and I have an implementation backed by the Google Guava AbstractSetMultimap and a MapMaker computing map that creates on demand the values-collections as a set view over a ConcurrentHashMap. With some care over the view collections and various wrappers, I think this gets pretty close.
The big problem, which has already been discussed by others who have tried this, appears to be that of removing the values-collections from the underlying map when they become empty, without introducing race conditions.
A couple of options appear to exist.
Questions:
Thanks
Edit: see also the discussion here on the guava mailing list.
Edit 2: I've since written this up. Please see this Google code area for an implementation. I would greatly appreciate any feedback from anyone who tries it, there rather than here.
As a follow-up, here are some details I omitted from the earlier discussions, which you linked to, about my concurrent multimap implementation.
That implementation followed your first suggestion: leaving empty collections in the backing map. The following live-view behavior complicates your other suggestions.
Multimap<String, Integer> multimap = HashMultimap.create();
Set<Integer> set = multimap.get("foo");
multimap.put("foo", 1);
int count = set.size(); // equals 1
For a real-world application, as opposed to a collection library class, something less than a fully concurrent multimap would probably suffice. You could define your own class that implements a subset of the Multimap interface or a limited selection of concurrency guarantees. Or, your application logic could minimize contention of a synchronized multimap to avoid performance problems.