H开发者_运维百科ow can we do that with Guava? Notice the presence of List<K>
in the return type since many keys can map to the same value in any normal map.
public static <K, V> Map<V, List<K>> inverse(Map<K, V> map){
Map<V, List<K>> result = new LinkedHashMap<V, List<K>>();
for (Map.Entry<K, V> entry : map.entrySet()) {
if(!result.containsKey(entry.getValue())){
result.put(entry.getValue(), new ArrayList<K>());
}
result.get(entry.getValue()).add(entry.getKey());
}
return result;
}
BiMap
seems to insist on the unicity of the values, but I don't have this luxury.
You can do this:
Map<K, V> map = ...;
ListMultimap<V, K> inverse = Multimaps.invertFrom(Multimaps.forMap(map),
ArrayListMultimap.<V,K>create());
Do note that pretty much any time you write Map<K, List<V>>
or Map<K, Set<V>>
or some such, a ListMultimap<K, V>
or SetMultimap<K, V>
is what you really want.
Use a Multimap instead, pick one that uses a list, like ArrayListMultimap, that will allow dupes.
Also you don't have to write your own invert method, there's one provided in com.google.common.collect.Multimaps.
In case someone stumbles here now (well within Java's Stream
era), here are two single-expression Stream
-based solutions:
1) Immutable version based on ImmutableListMultimap
+ toImmutableListMultimap
collector
ImmutableListMultimap<V, K> output = inputMap.entrySet().stream()
.collect(ImmutableListMultimap.toImmutableListMultimap(Map.Entry::getValue, Map.Entry::getKey));
2) Mutable version based on ArrayListMultimap
+ Multimaps.toMultimap
collector
ListMultimap<V, K> output = inputMap.entrySet().stream()
.collect(Multimaps.toMultimap(Map.Entry::getValue, Map.Entry::getKey, ArrayListMultimap::create));
精彩评论