3

我有一个 Map,其中键是字符串,值是逗号分隔的值列表。

如何反转键/值对的顺序并分配给新 Map 以便键成为值,值成为键

所以 :

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

变成:

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

一种可能的解决方案是迭代每个值,然后迭代每个键以搜索相同的对应值。如果找到,则将此新键/值对添加到新 Map。这似乎效率低下?

解决方案(使用接受的答案实施):

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

}
4

5 回答 5

3

看来您有很多要映射的地图。

这可以表示为

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());
    }
}
于 2012-09-17T11:07:11.213 回答
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());
    }
}

请注意,这不会对逆映射中的字符串进行排序。为此,您然后通过逆映射拆分和重新加入字符串进行第二次迭代。

更好的解决方案是将数据建模为SortedMap<String,SortedSet<String>>

于 2012-09-17T11:11:27.920 回答
2

您可以使用 Google Guava 的BiMap

 BiMap<?, ?> bimap = HashBiMap. create();
 BiMap<?, ?> reverse = bimap.inverse(); // Do this only once after the BiMap has been created.
于 2012-09-17T11:15:57.727 回答
1

如果值是列表,这可能会有所帮助:

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);
        }
    }
}
于 2012-09-17T11:49:49.870 回答
0
Map<Value, Key> reverseMap = new HashMap<Value, Key>();
for (Map.Entry<Key, Value> entry : map) {
    reverseMap.put(entry.getValue(), entry.getKey());
}

假设是每个(键,值)对在原始映射中都是不同的,因此在反转映射的过程中没有覆盖。

于 2012-09-17T11:02:05.650 回答