Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to transform key/value in Map

Tags:

java

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

}
like image 226
blue-sky Avatar asked Jun 28 '26 23:06

blue-sky


2 Answers

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());
    }
}
like image 113
Peter Lawrey Avatar answered Jun 30 '26 13:06

Peter Lawrey


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

like image 36
Stephen Connolly Avatar answered Jun 30 '26 12:06

Stephen Connolly