【问题标题】:Reverse HashMap keys and values in JavaJava中的反向HashMap键和值
【发布时间】:2013-12-23 02:56:53
【问题描述】:

这是一个简单的问题, 我有一个简单的 HashMap,我想反转它的键和值。

HashMap<Character, String> myHashMap = new HashMap<Character, String>();
myHashMap.put('a', "test one");
myHashMap.put('b', "test two");

我想创建一个新的 HashMap,在其中放置对立面。

HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();
e.g. Keys "test one" & "test two" and values 'a' & 'b'.

【问题讨论】:

  • 简单的问题,简单的答案。你能告诉我们你卡在哪里了吗?
  • 首先你必须确保你的价值观是独一无二的。否则应该是Map&lt;String, List&lt;Character&gt;&gt;
  • 好吧,我对 JAVA 还很陌生,不知道从哪里开始......它们都是独一无二的,是的
  • 这并不总是可以做到不丢失数据。想象一下你有这个:a -> test one; b -> 测试二; c -> 测试一个(在你的第一张地图中)。您将在第二张(输出)地图中得到什么?像这样:测试一个-> a(或c);测试二-> b。所以第一张地图有 3 个条目,第二张地图只有 2 个。

标签: java hashmap


【解决方案1】:

遍历键和值列表,然后添加它们。

HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();
for (String key : myHashMap.keySet()){
    reversedHashMap.put(myHashMap.get(key), key);
}

【讨论】:

  • entrySet 更好,不必对每个get计算哈希码
  • @A4L 确实如此,但对于简单的任务来说,差别不大。
【解决方案2】:

它们都是独一无二的,是的

如果您确定您的值是唯一的,您可以遍历旧地图的条目。

Map<String, Character> myNewHashMap = new HashMap<>();
for(Map.Entry<Character, String> entry : myHashMap.entrySet()){
    myNewHashMap.put(entry.getValue(), entry.getKey());
}

或者,您可以使用像Guava 提供的双向地图并使用inverse() 方法:

BiMap<Character, String> myBiMap = HashBiMap.create();
myBiMap.put('a', "test one");
myBiMap.put('b', "test two");

BiMap<String, Character> myBiMapInversed = myBiMap.inverse();

已经出局了,你也可以这样操作:

Map<String, Integer> map = new HashMap<>();
map.put("a",1);
map.put("b",2);

Map<Integer, String> mapInversed = 
    map.entrySet()
       .stream()
       .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey))

最后,我将我的贡献添加到 proton pack library,其中包含 Stream API 的实用方法。有了它,你可以这样做:

Map<Character, String> mapInversed = MapStream.of(map).inverseMapping().collect();

【讨论】:

  • 感谢您解释双向地图的使用。我不知道,它对我真的很有用!
  • 当我对收集器使用您的 java-8 方法时,Map.Entry::getValuegetKey 上出现以下错误:Non-static method cannot be referenced from a static context
  • Jan,这是因为您的地图与使用 mapInversed 变量声明的通用类型不同。
  • 如果值重复怎么办?你是怎么处理的?
  • @ChaitanyaUttarwar 您必须找到一种合并策略来映射与原始映射中相同值相关联的不同键(您可以将它们分组到一个列表中,对它们求和,只取一个关键取决于您想要实现的目标)。
【解决方案3】:

要回答有关如何执行此操作的问题,您可以从地图中获取entrySet,然后将getValue 用作key 并将getKey 用作value 将其放入新地图。

但请记住,Map 中的键是唯一的,这意味着如果您的原始映射中有一个具有两个不同键的值,则只有第二个键(按迭代顺序)将保留为新映射中的值。

【讨论】:

    【解决方案4】:

    我写了一个更简单的循环也可以工作(注意我所有的值都是唯一的):

    HashMap<Character, String> myHashMap = new HashMap<Character, String>();
    HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();
    
    for (char i : myHashMap.keySet()) {
        reversedHashMap.put(myHashMap.get(i), i);
    }
    

    【讨论】:

      【解决方案5】:

      Apache commons 集合库提供了一种用于反转地图的实用方法。如果您确定 myHashMap 的值是唯一的,则可以使用它

      org.apache.commons.collections.MapUtils.invertMap(java.util.Map map)
      

      示例代码

      HashMap<String, Character> reversedHashMap = MapUtils.invertMap(myHashMap) 
      

      【讨论】:

        【解决方案6】:
        private <A, B> Map<B, A> invertMap(Map<A, B> map) {
            Map<B, A> reverseMap = new HashMap<>();
            for (Map.Entry<A, B> entry : map.entrySet()) {
                reverseMap.put(entry.getValue(), entry.getKey());
            }
            return reverseMap;
        }
        

        请务必记住,put 在使用相同键调用时会替换值。因此,如果您的映射有两个具有相同值的键,则倒置映射中将只有其中一个存在。

        【讨论】:

        • 我认为关于如何处理重复值成为键的注释会很有用。
        • @CHBuckingham 同意
        【解决方案7】:

        如果值不是唯一的,反转映射的安全方法是使用 java 8 的 groupingBy 函数

        Map<String, Integer> map = new HashMap<>();
        map.put("a",1);
        map.put("b",2);
        
        Map<Integer, List<String>> mapInversed = 
        map.entrySet()
           .stream()
           .collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())))
        

        【讨论】:

          【解决方案8】:

          使用以下示例 sn-p 进行测试,使用 MapUtils 和 Java8 Stream 功能进行了测试。它适用于两种情况。

          public static void main(String[] args) {
              Map<String, String> test = new HashMap<String, String>();
              test.put("a", "1");
              test.put("d", "1");
              test.put("b", "2");
              test.put("c", "3");
              test.put("d", "4");
              test.put("d", "41");
          
              System.out.println(test);
          
              Map<String, String> test1 = MapUtils.invertMap(test);
          
              System.out.println(test1);
          
              Map<String, String> mapInversed = 
                      test.entrySet()
                         .stream()
                         .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
          
              System.out.println(mapInversed);
          }
          
          Output:
          {a=1, b=2, c=3, d=41}
          {1=a, 2=b, 3=c, 41=d}
          {1=a, 2=b, 3=c, 41=d}
          

          【讨论】:

            【解决方案9】:

            用于反转字典数组。 (如果值是唯一的)

            private void reverseArrayMap(List<Map<String, String>> list) {
                // reversing the array of dictionary
                List<Map<String, String>> newList = new ArrayList<>();
                Map<String, String> resDic = new HashMap<>();
            
                for (Map<String, String> map : list) {
                    map.forEach((key, value) -> resDic.put(value, key));
                    newList.add(resDic);
                }
            
                System.out.println("Original Array of Dictionary" + list);
                System.out.println("Reversed Array of Dictionary" + newList);
            }      
            

            【讨论】:

              【解决方案10】:

              用于还原地图,在您的情况下:

              private void reverseMap(Map<Character, String> map) {
                  Map<String, Character> newList = new HashMap<>();
                  map.forEach((key, value) -> newList.put(value, key));
                  System.out.println(newList);
              }
              

              或者你可以遍历旧的hashmap

              HashMap<String, Character> newList = new HashMap<String, Character>();
              for (String key : list.keySet()){
                 newList.put(list.get(key), key);
              }
              

              【讨论】:

                【解决方案11】:

                使用 Java 8 中引入的 forEach

                Map<Short, String> regularMap = new HashMap<>();
                Map<String, Short> inversedMap = new HashMap<>();
                
                regularMap.forEach((key, value) -> inversedMap.put(value, key));
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-11-11
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-09-04
                  • 2010-12-12
                  • 2023-03-08
                  相关资源
                  最近更新 更多