简体   繁体   中英

How to transform key/value in Map

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

}

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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM