views:

81

answers:

2

How 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.

+3  A: 

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.

Nathan Hughes
+6  A: 

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.

ColinD
Nice, that was fast.
lacroix1547
But is is annoying to be forced to convert to Multimap. And considering the effort they put on performances, it may be improved in the future, with something more sexy.
lacroix1547
@lacroix1547 Huh? `Multimaps.forMap()` returns a _view_ of the given map. It does almost no work... it just calls a constructor and assigns the map to a field. That's it. Consider it an adapter that allows you to use a map with methods like `invertFrom()` that expect a `Multimap`.
ColinD
Yeah ok I didnt opened forMap. I guess was right :) they put efforts on performances.
lacroix1547