【问题标题】:How print out the contents of a HashMap<String, String> in ascending order based on its values?如何根据值以升序打印 HashMap<String, String> 的内容?
【发布时间】:2011-04-06 00:51:57
【问题描述】:

我有这个HashMap,我需要根据其中包含的不是键)。

但是我打印出来的顺序似乎是随机的。

升序打印出来的最佳方式是什么?

Map<String, String> codes = new HashMap<String, String>();

codes.put("A1", "Aania");
codes.put("X1", "Abatha");
codes.put("C1", "Acathan");
codes.put("S1", "Adreenas");

换句话说,上面的例子应该是这样打印出来的:

A1, Aania
X1, Abatha
C1, Acathan
S1, Adreenas

【问题讨论】:

标签: java sorting hashmap


【解决方案1】:

我认为最简单最短的代码是这样的:

public void listPrinter(LinkedHashMap<String, String> caseList) {

    for(Entry entry:caseList.entrySet()) {
        System.out.println("K: \t"+entry.getKey()+", V: \t"+entry.getValue());
    }
}

【讨论】:

    【解决方案2】:

    Java 8

    map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(System.out::println);
    

    【讨论】:

      【解决方案3】:

      您无法仅从 HashMap 类中执行此操作。

      我会采用Map&lt;String, String&gt; codes,构造一个TreeMap&lt;String, String&gt; reversedMap 的反向映射,在其中将codes 映射的值映射到键(这需要您的原始映射从键值对)。由于 TreeMap 提供了迭代器,它以升序键顺序返回条目,这将为您提供您想要的顺序(按值排序)的第一个映射的值/键组合。

      Map<String, String> reversedMap = new TreeMap<String, String>(codes);
      
      //then you just access the reversedMap however you like...
      for (Map.Entry entry : reversedMap.entrySet()) {
          System.out.println(entry.getKey() + ", " + entry.getValue());
      }
      

      有几个集合库(commons-collections、Google Collections 等)具有类似的双向 Map 实现。

      【讨论】:

      • 为什么需要第二个循环?只需创建一个临时映射并从codes 添加切换键和值?
      • 没必要,这是一个访问reversedMap并对条目做一些事情的例子
      • 如果 map 中的两个条目具有不同的键但相同的值怎么办?此代码将删除其中一个...
      • @akb 这就是为什么我说这将要求您的原始地图具有从键到值的一对一映射
      • System.out.println(entry.getValue() + ", " + entry.getKey()); 复制 OP 的原始打印输出
      【解决方案4】:

      你只需要使用:

       Map<>.toString().replace("]","\n");
      

      并将每个 key=value 集的结尾方括号替换为新行。

      【讨论】:

        【解决方案5】:

        您可以使用条目集的列表而不是键集,这是一个更自然的选择,因为您是根据值进行排序的。这样可以避免在条目的排序和打印过程中进行大量不必要的查找。

        Map<String, String> map = ...
        List<Map.Entry<String, String>> listOfEntries = new ArrayList<Map.Entry<String, String>>(map.entrySet());
        Collections.sort(listOfEntries, new SortByValueComparator());
        for(Map.Entry<String, String> entry: listOfEntries)
           System.out.println(entry);
        
        static class SortByValueComparator implements Comparator<Map.Entry<String, String>> {
           public int compareTo(Map.Entry<String, String> e1, Map.Entry<String, String> e2) {
               return e1.getValue().compateTo(e2.getValue());
           }
        }
        

        【讨论】:

          【解决方案6】:
          while (itr.hasNext()) {
              Vehicle vc=(Vehicle) itr.next();
              if(vc.getVehicleType().equalsIgnoreCase(s)) {
                  count++;
              }
          }
          

          【讨论】:

          • 这是为了回答另一个问题而发布的吗?如果有,请在此处删除。
          【解决方案7】:

          试试:

          try
          {
              int cnt= m.getSmartPhoneCount("HTC",true);      
              System.out.println("total count of HTC="+cnt);
          }  
          catch (NoSuchBrandSmartPhoneAvailableException e)
          {
              // TODO Auto-generated catch 
              e.printStackTrace();
          }
          

          【讨论】:

          • 这是为了回答另一个问题而发布的吗?如果有,请在此处删除。
          【解决方案8】:

          是时候添加一些 lambdas 了:

          codes.entrySet()
              .stream()
              .sorted(Comparator.comparing(Map.Entry::getValue))
              .forEach(System.out::println);
          

          【讨论】:

          • 这不会打印字符串值,除非我在这里遗漏了一些东西。
          • @almostabeginner Code forEach(System.out::println) 将打印每个条目。检查this
          • 我认为这只会打印地址,而不是值?我试过但没有用。我的地图包含两个对象,键是一个“人”对象,它有一个名字、姓氏字段等,我想打印名字,我看不出这段代码是如何做到的?感谢您的宝贵时间。
          • @almostabeginner 准确地说,这段代码打印地图中的所有Entry,隐式调用它们的toString 方法。如果要打印键或键中的某些字段,可以执行以下操作:codes.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).map(Map.Entry::getKey).map(Person::getLastName).forEach(System.out::println);
          • 感谢 Vladimir S. 的帮助,尊重 :)
          【解决方案9】:
           SmartPhone[] sp=new SmartPhone[4];
           sp[0]=new SmartPhone(1,"HTC","desire","black",20000,10,true,true);
           sp[1]=new SmartPhone(2,"samsung","grand","black",5000,10,false,true);
           sp[2]=new SmartPhone(14,"google nexus","desire","black",2000,30,true,false);
           sp[3]=new SmartPhone(13,"HTC","desire","white",50000,40,false,false);
          

          【讨论】:

          【解决方案10】:

          for(Map.Entry entry: codes.entrySet()) 的 for 循环对我不起作用。改用迭代器。

          Iterator<Map.Entry<String, String>> i = codes.entrySet().iterator(); 
          while(i.hasNext()){
              String key = i.next().getKey();
              System.out.println(key+", "+codes.get(key));
          }
          

          【讨论】:

          • 这没有回答问题,因为您正在迭代原始的 HashMap,它没有排序。
          【解决方案11】:

          最简单的解决方案是使用像 TreeMap 这样的排序映射而不是 HashMap。 如果您无法控制地图构造,那么最小的解决方案是构造一组排序的键。你真的不需要一张新地图。

          Set<String> sortedKeys = new TreeSet<String>();
          sortedKeys.addAll(codes.keySet());
          
          for(String key: sortedKeys){
              println(key  + ":" + codes.get(key));
          }
          

          【讨论】:

          • OP 希望输出按值排序,而不是按键。
          • 删除这个 - 不回答问题
          【解决方案12】:
          1. 创建TreeMap&lt;String,String&gt;
          2. 添加每个HashMap 条目,并将值作为键。
          3. 迭代 TreeMap

          如果值不唯一,则需要在第二个位置列出一个列表。

          【讨论】:

          • 美丽。不得不删除我的答案:)
          • 不太正确... "SortedMap 接口的基于红黑树的实现。此类保证地图将按键升序排列,根据键的类的自然顺序排序(请参阅 Comparable),或者由创建时提供的比较器,具体取决于使用的构造函数。”您将按键而不是值对其进行排序。
          【解决方案13】:

          您需要制作一个键列表,根据相应的值对它们进行排序,然后遍历排序后的键。

          Map<String, String> map = getMyMap();
          List<String> keys = new ArrayList<String>(map.keySet());
          Collections.sort(keys, someComparator);
          for (String key: keys) {
              System.out.println(key + ": " + map.get(key));
          }
          

          至于someComparator 的用途,这里有一些我经常觉得有用的方便、通用的比较器创建例程。第一个根据值的自然顺序对值进行排序,第二个允许您指定任意 Comparator 对值进行排序:

          public static <K, V extends Comparable<? super V>>
                  Comparator<K> mapValueComparator(final Map<K, V> map) {
              return new Comparator<K>() {
                  public int compare(K key1, K key2) {
                      return map.get(key1).compareTo(map.get(key2));
                  }
              };
          }
          
          public static <K, V>
                  Comparator<K> mapValueComparator(final Map<K, V> map,
                                                   final Comparator<V> comparator) {
              return new Comparator<K>() {
                  public int compare(K key1, K key2) {
                      return comparator.compare(map.get(key1), map.get(key2));
                  }
              };
          }
          

          【讨论】:

            猜你喜欢
            • 2022-01-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-06-01
            • 2014-05-13
            • 2021-12-12
            • 1970-01-01
            相关资源
            最近更新 更多