Is there a way to create (/return) an unmodifiable Multimap?
I am using the Multimap of com.google.common.collect and need to create an unmodfiable Multimap, but I couldn't find a lib that has a method, which returns the a given Multimap as an umodifiable Multimap.
For "normal" Maps I usually use the MapUtils.unmodifiableMap(map) method of the org.apache.commons.collections4.MapUtils lib.
example:
public static Map<String, String> bufferName()
{
Map<String, String> fooMap = new HashMap<>();
fooMap.put("foo", "bar");
return MapUtils.unmodifiableMap(fooMap);
}
what I need:
public static Multimap<String, String> bufferName1()
{
HashMultimap<String, String> fooMultimap = HashMultimap.create();
fooMultimap.put("foo", "bar");
fooMultimap.put("foo", "foobar");
// ! the next line needs to be optimized so that the returned HashMultimap cannot be modified.
return fooMultimap;
}
I tried to find a lib, that can return given mutable Multimaps as immutable Multimaps, but couldn't find any.
I also tried to put the mutable Multimap into an immmutable Object, but that is everything else than clean.
example:
public static Set<HashMultimap<String, String>> bufferName1()
{
HashMultimap<String, String> fooMultimap = HashMultimap.create();
fooMultimap.put("foo", "bar");
fooMultimap.put("foo", "foobar");
// org.apache.commons.collections4.SetUtils
SetUtils.unmodifiableSet(Set.of(fooMultimap));
}
CodePudding user response:
Java's own core library is a general purpose library.
Guava is a general purpose library.
Apache commons is a general purpose library.
You're using all 3 in a weird mix and match. This isn't a good idea. Generally the apache stuff is exceedingly low quality. The reason guava and apache-commons exist in the first place is due to perceived lack of utility in the core libs, but in the last decade or so (note that guava and apache-commons are much, much older), the core libs have been adding stuff at rapid pace.
Thus, I'd get rid of apache for sure, and possibly guava as well; core libs can do all this now.
Getting an immutable multimap using just guava
Guava has class ImmutableListMultimap
and ImmutableSetMultimap
. They have a copyOf
static 'constructor'. So just ImmutableSetMultimap.copyOf(myMutableMultimap)
is all you need.
Getting an immutable multimap using just java core
Java core does multimaps a little different. Instead of a Multimap<Integer, String>
, you have a Map<Integer, List<String>>
(or Set<String>
, mirroring how guava's multimap has 'SetMultimap' and 'ListMultimap' variants). The major downside to it, and presumably the reason guava has multimaps in the first place, is that adding a new element sounds really complicated; you have to get the set/list first. If it exists, use it. If it does not exist, create it, then use that.
Except since Java9 it's not that complicated anymore:
Map<Integer, List<String>> multimap = new HashMap<>();
int k = 5;
String v = "hello";
// add a new item:
multimap.computeIfAbsent(5, x -> new ArrayList<>()).add(v);
computeIfAbsent
is the key that makes this palatable.
Given that it's "just a map", you can use Collections.unmodifiableMap()
as usual.
Guava's multimap still has advantages; you may want to continue to use it.
But apache cannot help here.