3

I have a Map where key is a String and value is comma seperated list of values.

How can I reverse the ordering of the key/value pairs and assign to new Map so that keys become values and the values become keys

So :

key   value
key1  value1,value2,value3
key2  value1,value4,value5        
key3  value4,value2,value1

becomes :

key       value
value1    key1,key2,key3
value2    key1,key3
value3    key1
value4    key2,key3
value5    key2

A possible solution is to iterate over each value and then iterate of every key searching for same corresponding value. If found add this new key/value pair to a new Map. This seems inefficient ?

Solution (implemented using accepted answer) :

import java.util.HashMap;
import java.util.Map;

public class MapTransformer {

    public static void main(String args[]) {

        Map<String, String> m1 = new HashMap<String, String>();

        m1.put("key1", "value1,value2");
        m1.put("key2", "value5");
        m1.put("key3", "value4,value2,value1");

        Map<String, String> inverseMap = new HashMap<String, String>();
        for (Map.Entry<String, String> entry : m1.entrySet()) {
            for (String value : entry.getValue().split(",")) {
                if (inverseMap.containsKey(value))
                    inverseMap.put(value, inverseMap.get(value) + "," + entry.getKey());
                else
                    inverseMap.put(value, entry.getKey());
            }
        }

        for (Map.Entry<String, String> entry : inverseMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+" "+value);
        }
    }

}
blue-sky
  • 51,962
  • 152
  • 427
  • 752
  • You can also check this. Looks similar. http://stackoverflow.com/questions/7549640/reversing-a-hashmap-from-mapstring-boolean-to-mapboolean-liststring – titogeo Sep 18 '12 at 06:13

5 Answers5

3

It appears you have a many to map Map.

This can be represented using

Map<K, List<V>> map1 = new LinkedHashMap<K, List<V>>();
Map<V, List<K>> map2 = new LinkedHashMap<V, List<K>>();
for (Map.Entry<K, List<V>> entry : map1.entrySet()) {
    for (V v : entry.getValue()) {
        List<K> list2 = map2.get(v);
        if (list2 == null)
            map2.put(v, list2 = new ArrayList<K>());
        list2.add(entry.getKey());
    }
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
2
Map<String,String> initialMap = ...
Map<String,String> inverseMap = new HashMap<String,String>();
for (Map.Entry<String,String> entry: initialMap.entrySet()) {
    for (String v : entry.getValue().split(",")) {
        if (inverseMap.containsKey(v)) 
          inverseMap.put(v,inverseMap.get(v)+","+entry.getKey());
        else
          inverseMap.put(v, entry.getKey());
    }
}

Note that this does not sort the strings in the inverse map. To do that you then do a second iteration through the inverse map splitting and rejoining the strings.

A better solution is to model the data as a SortedMap<String,SortedSet<String>>

Stephen Connolly
  • 13,872
  • 6
  • 41
  • 63
2

You can use Google Guava's BiMap:

 BiMap<?, ?> bimap = HashBiMap. create();
 BiMap<?, ?> reverse = bimap.inverse(); // Do this only once after the BiMap has been created.
Alexandre Dupriez
  • 3,026
  • 20
  • 25
1

If value is list this maybe help:

Map<String, List<String>> reverseMap = new HashMap<String, List<String>>();

for(Entry`<String, List<String>>` entry : map.entrySet())
{
    for(String str : entry.getValue())
    {
        if(reverseMap.get(str) != null){
            reverseMap.get(str).add(entry.getKey());            
        } else {
            List<String> list = new ArrayList<String>();
            list.add(entry.getKey());
            reverseMap.put(str, list);
        }
    }
}
Jake1164
  • 12,291
  • 6
  • 47
  • 64
Alex K
  • 56
  • 3
0
Map<Value, Key> reverseMap = new HashMap<Value, Key>();
for (Map.Entry<Key, Value> entry : map) {
    reverseMap.put(entry.getValue(), entry.getKey());
}

The assumption is that each (key, value) pair is distinct in the original map, so there are no overwrites during the process of reversing the map.

Vikdor
  • 23,934
  • 10
  • 61
  • 84