lacroix1547
lacroix1547

Reputation: 1070

How to do map inversion with Guava with non-unique values?

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.

Upvotes: 19

Views: 12762

Answers (3)

Tomasz Linkowski
Tomasz Linkowski

Reputation: 4496

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));

Upvotes: 1

Nathan Hughes
Nathan Hughes

Reputation: 96454

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.

Upvotes: 7

ColinD
ColinD

Reputation: 110104

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.

Upvotes: 36

Related Questions