【问题标题】:Invert Map | Values ---> Keys反转地图 |值 ---> 键
【发布时间】:2020-03-16 21:06:43
【问题描述】:

我希望能够反转具有多个键的给定 HashMap 可以指向相同的值。

HashMap<String, String> cities = new HashMap<String, String>();

        cities.put("Manchester", "UK");
        cities.put("London", "UK");
static HashMap<String, String> inverseMap(HashMap map) {
       // something that has "UK" point to both "Manchester" and "London"

      // if it can be done without using any special Java 8 feature, that would be great
}

我不确定从哪里开始。

【问题讨论】:

  • 逆HashMap是什么意思?
  • 当您使用键 -> 值创建地图时,我希望能够获取给定的地图并创建一个新的地图,其中值 -> 键。就我而言,我希望它在多个键指向单个值的情况下工作,因此打印的 inverse 将打印链接到单个值的所有键。
  • 您要求的内容与地图的基本理念背道而驰。我认为在这种情况下,您可以使用“反向映射”做的最好的事情是拥有一个 Map> 以便您的数据只有一个“UK”条目,其中包含 [ “曼彻斯特”、“伦敦”]
  • @Ryan 这正是我想要的。我不知道为什么,但这并没有出现在我的脑海中,但这就是我想要的。干杯,伙计。

标签: java dictionary inverse


【解决方案1】:

这样做。基本上,它使用了一个合并函数来连接重复键的值。

  • 创建新地图
  • 使用旧地图的值作为新地图的键
  • 如果新映射没有键的值,请将值放入新映射中
  • 否则,将该值连接到该键的旧值
        HashMap<String, String> cities = new HashMap<String, String>();

        cities.put("Manchester", "UK");
        cities.put("London", "UK");
        cities.put("New York", "US");
        cities.put("Chicago", "US");

        Map<String,String> inverted = new HashMap<>();
        for (String key : cities.keySet()) {
            String newKey = cities.get(key);
            String value = inverted.get(newKey);
            if (value == null) {
                inverted.put(newKey, key);
            } else {
                value = value + ", " + key;
                inverted.put(newKey, value);
            }

        }
        for (Entry<String,String> e : inverted.entrySet()) {
            System.out.println(e.getKey() + " -> " + e.getValue());
        }

打印出来

UK -> Manchester, London
US -> New York, Chicago

由于您没有指定如何处理重复键。我也可以将其存储在Map&lt;String,List&lt;String&gt;&gt;

【讨论】:

    【解决方案2】:

    这就是你要找的吗?

    Map<String, String> cities = new HashMap<>();
    cities.put("Manchester", "UK");
    cities.put("London", "UK");
    Map<String, List<String>> reverseMap = new HashMap<>();
    for (Entry<String, String> entry : cities.entrySet()) {
         List<String> list = reverseMap.get(entry.getValue());
         if (list == null) {
             list = new ArrayList<>();
             reverseMap.put(entry.getValue(), list);
         }
         list.add(entry.getKey());
    }
    
    System.out.println(reverseMap);
    

    【讨论】:

      【解决方案3】:

      由于多个键可以包含相同的值,因此您必须能够在反向映射中为每个键存储多个值。我建议为此使用 Set 作为值。

      • 创建可以将一组字符串保存为值的映射
      • 遍历原始地图
      • 如果在新地图中找不到该国家/地区,请在此处创建一个条目
      • 将城市添加到地图中

      这也应该适用于没有依赖关系的 Java 7。

      static HashMap<String, Set<String>> inverseMap(HashMap<String,String> map) {
          HashMap<String,Set<String>> inversed=new HashMap<>();
          for(Map.Entry<String,String> entry:map.entrySet()){
              if(!inversed.containsKey(entry.getValue())){
                  inversed.put(entry.getValue(),new HashSet<>());
              }
              inversed.get(entry.getValue()).add(entry.getKey());
          }
          return inversed;
      }
      

      {Manchester=UK,London=UK} 会变成{UK={Manchester,London}}(顺序可能不同)。

      【讨论】:

      • 你尝试编译了吗?
      • 手机无法编译。
      • 哦,我忘了.entrySet()
      • 很少有结束括号。但对于电话接听来说还不错。
      【解决方案4】:

      您可以查看 MultiMap。它允许将单个键映射到多个值。

      这已经在 Google Guava 中实现了 https://guava.dev/releases/19.0/api/docs/com/google/common/collect/Multimap.html

      ListMultimap<String, String> multimap = ArrayListMultimap.create();
         for (President pres : US_PRESIDENTS_IN_ORDER) {
           multimap.put(pres.firstName(), pres.lastName());
         }
         for (String firstName : multimap.keySet()) {
           List<String> lastNames = multimap.get(firstName);
           out.println(firstName + ": " + lastNames);
         }
      ... produces output such as:
         Zachary: [Taylor]
         John: [Adams, Adams, Tyler, Kennedy]  // Remember, Quincy!
         George: [Washington, Bush, Bush]
         Grover: [Cleveland, Cleveland]        // Two, non-consecutive terms, rep'ing NJ!
      

      在 Apache Commons Collections 中 https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/MultiValuedMap.html

           MultiValuedMap<K, String> map = new MultiValuedHashMap<K, String>();
           map.put(key, "A");
           map.put(key, "B");
           map.put(key, "C");
          Collection<String> coll = map.get(key);
      coll will be a collection containing "A", "B", "C".
      

      【讨论】:

      • // 如果不使用任何特殊的 Java 8 功能就可以做到,那就太好了
      • 这些库本身并没有链接到 java 8。Commons 集合的 MultiValuedMap 从 4.1 版开始,需要 java 6。commons.apache.org/proper/commons-collections/release_4_1.html
      • 我认为依赖不是 java 8 的特性,我认为 OP 意味着流......
      • 现在我很困惑 :) 如果目标是做一个自己的自定义实现,可以简单地查看任何一个的源代码。如果目标是让它正常工作,我会使用经过验证的库(番石榴、公共收藏)
      【解决方案5】:

      您可以遍历原始地图的条目集并使用值(国家代码)作为键并将每个键(城市)添加到列表中:

      static HashMap<String, List<String>> inverseMap(HashMap<String, String> map) {
         HashMap<String, List<String>> countryToCity = new HashMap<>();
         for(Map.Entry<String,String> entry: map.entrySet()){
             countryToCity.computeIfAbsent(entry.getValue(), k -> new ArrayList<>()).add(entry.getKey());
         }
         return countryToCity;
      }
      

      【讨论】:

      • ComputeIfAbsent 是 Java 8 的一项功能。OP 不希望这样。
      猜你喜欢
      • 2021-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多