如何根据值以升序打印 HashMap<String, String> 的内容?

Posted

技术标签:

【中文标题】如何根据值以升序打印 HashMap<String, String> 的内容?【英文标题】:How print out the contents of a HashMap<String, String> in ascending order based on its values? 【发布时间】: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

【问题讨论】:

可能重复:***.com/questions/109383/… 只是好奇。用例是什么?我的猜测是您选择了错误的数据结构并尝试对其进行调整以适合您的规格。 【参考方案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);

【讨论】:

介意explain your solution 一点吗?您可能想阅读How Do I Write A Good Answer。 这是为了回答另一个问题而发布的吗?如果有,请在此处删除。【参考方案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】:
    创建TreeMap&lt;String,String&gt; 添加每个HashMap 条目,并将值作为键。 迭代 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));
        
    ;

【讨论】:

以上是关于如何根据值以升序打印 HashMap<String, String> 的内容?的主要内容,如果未能解决你的问题,请参考以下文章

java hashmap按照value来排序

如何从 rxjs 流中过滤单个值以在 Angular 2 组件中打印

java hashMap<int ,String[] > 根据map的value值排序.

如何从 WCF 打印数组的值以形成标签?

JAVA这个能分页吗? List<HashMap<String, String>> list = new ArrayList<HashMap<String, Str

如何决定使用 HashMap 还是 TreeMap?