【问题标题】:How to group the keys from a HashMap using values as a List or an Array如何使用值作为列表或数组对 HashMap 中的键进行分组
【发布时间】:2017-09-14 12:35:49
【问题描述】:

我创建了一个使用 String 作为键和 Integer 作为值的 Map。所以,就像citiesWithCodes

到目前为止,出于测试目的,我已手动将值放入 Hashmap 中。它们是:

Map<String, Integer> citiesWithCodes = new HashMap<String, Integer>();
        citiesWithCodes.put("Berlin", 49);
        citiesWithCodes.put("Frankfurt", 49);
        citiesWithCodes.put("Hamburg", 49);
        citiesWithCodes.put("Cologne", 49);
        citiesWithCodes.put("Salzburg", 43);
        citiesWithCodes.put("Vienna", 43);
        citiesWithCodes.put("Zurich", 41);
        citiesWithCodes.put("Bern", 41);
        citiesWithCodes.put("Interlaken", 41);

我想根据城市的代码以列表或数组格式获取城市。因此,例如对于值 43,它应该返回类似 {43=[Vienna, Salzburg]} 的内容。

我尝试了以下方法。这绝对是一种肮脏的方法,并且没有给出正确的结果。

   public static Map<Integer, List<String>> codeCities(Map<String, Integer> citiesWithCodes){
       Map<Integer, List<String>> segList = new HashMap<Integer, List<String>>();
       List<String> city;
       Iterator<Entry<String, Integer>> i = citiesWithCodes.entrySet().iterator();
       while (i.hasNext()) {
           city = new ArrayList<String>();
           Entry<String, Integer> next = i.next();
           i.remove();
           city.add(next.getKey());
           for (Entry<String, Integer> e : citiesWithCodes.entrySet()) {
               if(e.getValue().equals(next.getValue())){
                   city.add(e.getKey());
                   citiesWithCodes.remove(e);
               }
           }
           System.out.println(city);
           segList.put(next.getValue(), city);
       }
       return segList;
   }

我得到的输出是:{49=[Cologne], 41=[Interlaken], 43=[Salzburg]} 有人能告诉我,实现结果的正确方法吗?

PS:我知道使用 MultiMap 是可能的。但我们仅限于使用 Java Collection Framework,也不能使用 Java 8。

【问题讨论】:

  • 你可以使用 Java 8 吗?
  • @SchiduLuca。不幸的是,项目范围仅限于 Java 7。

标签: java hashmap key-value


【解决方案1】:

在 java 8 之前

package com.stackoverflow;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class HashMapToListMap {

public static void main(String[] args) {
    Map<String, Integer> citiesWithCodes = new HashMap<String, Integer>();
    citiesWithCodes.put("Berlin", 49);
    citiesWithCodes.put("Frankfurt", 49);
    citiesWithCodes.put("Hamburg", 49);
    citiesWithCodes.put("Cologne", 49);
    citiesWithCodes.put("Salzburg", 43);
    citiesWithCodes.put("Vienna", 43);
    citiesWithCodes.put("Zurich", 41);
    citiesWithCodes.put("Bern", 41);
    citiesWithCodes.put("Interlaken", 41);

    Map<Integer, List<String>> result = new HashMap<Integer, List<String>>();
    for(Entry<String,Integer> entry : citiesWithCodes.entrySet()){
            List<String> list = new ArrayList<String>();
            if(result.containsKey(entry.getValue()))
                list = result.get(entry.getValue());
            list.add(entry.getKey());
            result.put(entry.getValue(), list);
    }
    System.out.println(result);
}

}

java 8 之后

 package com.stackoverflow;

 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;

public class HashMapToListMap {

public static void main(String[] args) {
    Map<String, Integer> citiesWithCodes = new HashMap<String, Integer>();
    citiesWithCodes.put("Berlin", 49);
    citiesWithCodes.put("Frankfurt", 49);
    citiesWithCodes.put("Hamburg", 49);
    citiesWithCodes.put("Cologne", 49);
    citiesWithCodes.put("Salzburg", 43);
    citiesWithCodes.put("Vienna", 43);
    citiesWithCodes.put("Zurich", 41);
    citiesWithCodes.put("Bern", 41);
    citiesWithCodes.put("Interlaken", 41);


    Map<Integer, List<String>> result =  citiesWithCodes.entrySet().stream().collect(Collectors.groupingBy(
            Map.Entry::getValue,Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
    System.out.println(result);
}

}

【讨论】:

    【解决方案2】:

    如果您的范围仅限于 Java 7,请尝试按以下代码进行更改:

     Map<Integer, List<String>> segList = new HashMap<Integer, List<String>>();
     Iterator<Entry<String, Integer>> i = citiesWithCodes.entrySet().iterator();
                while (i.hasNext()) {
                      Entry<String, Integer> next = i.next();
                      if (segList.get(next.getValue()) != null) {
                           List<String> city= segList.get(next.getValue());
                           city.add(next.getKey());
                           segList.put(next.getValue(), city);
                      }else{
                            List<String> city=new ArrayList<String>();
                            city.add(next.getKey());
                            segList.put(next.getValue(), city);
    
                      }
                }
    

    输出:

    {49=[法兰克福、柏林、汉堡、科隆]、41=[伯尔尼、苏黎世、 因特拉肯], 43=[维也纳, 萨尔茨堡]}

    【讨论】:

      【解决方案3】:

      您总是构造一个新的List&lt;String&gt; 来保存具有给定键的城市列表。发生在一行

      city = new ArrayList<String>();
      

      替换为

      if(segList.containsKey(next.getValue())) {
          city = segList.get(next.getValue());
      } else {
          city = new ArrayList<String>();
      }
      

      并且代码应该按预期工作。

      编辑:@eran 更快,但我留下它,因为它解释了在不太优雅和现代的方法中所犯的错误。

      【讨论】:

      • 我需要在for 循环之前将值添加到city。所以,我不能只在else 部分启动它。
      • 此时与原代码没有区别。只需用我的 5替换你的一行。
      猜你喜欢
      • 2015-02-05
      • 2013-11-10
      • 2021-10-25
      • 1970-01-01
      • 1970-01-01
      • 2015-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多