33

I have this HashMap that I need to print out in ascending order according to the values contained in it (not the keys).

But the order when I print it out is seemingly random.

What's the best way to print it out in ascending value order?

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

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

In other words, the example above should print out as this:

A1, Aania
X1, Abatha
C1, Acathan
S1, Adreenas
Carlsberg
  • 547
  • 1
  • 5
  • 8
  • 1
    possible duplicate: http://stackoverflow.com/questions/109383/how-to-sort-a-mapkey-value-on-the-values-in-java – sje397 Aug 31 '10 at 00:38
  • 7
    Just curious. What is the use case? My guess is you have chosen a wrong data structure and trying to tweak it to suit your specs. – chedine Aug 31 '10 at 05:25

13 Answers13

41

You aren't going to be able to do this from the HashMap class alone.

I would take the Map<String, String> codes, construct a reverse map of TreeMap<String, String> reversedMap where you map the values of the codes Map to the keys (this would require your original Map to have a one-to-one mapping from key-to-value). Since the TreeMap provides Iterators which returns entries in ascending key order, this will give you the value/key combination of the first map in the order (sorted by values) you desire.

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());
}

There are several collections libraries (commons-collections, Google Collections, etc) which have similar bidirectional Map implementations.

catch23
  • 17,519
  • 42
  • 144
  • 217
matt b
  • 138,234
  • 66
  • 282
  • 345
11

You'll need to make a list of the keys, sort them according to the corresponding values, then iterate over the sorted keys.

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));
}

As for what to use for someComparator, here are some handy, generic Comparator-creating routines I often find useful. The first one sorts by the values according to their natural ordering, and the second allows you to specify any arbitrary Comparator to sort the values:

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));
        }
    };
}
Sean
  • 29,130
  • 4
  • 80
  • 105
6

It's time to add some lambdas:

codes.entrySet()
    .stream()
    .sorted(Comparator.comparing(Map.Entry::getValue))
    .forEach(System.out::println);
AlexW
  • 896
  • 7
  • 9
  • This does not print the String value, unless I'm missing something here. – almost a beginner Oct 15 '15 at 11:30
  • @almostabeginner Code `forEach(System.out::println)` will print every entry. Check [this](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#forEach-java.util.function.Consumer-) – AlexW Oct 15 '15 at 12:48
  • I think this only prints the address, rather than the value? I tried it but didn't work. My map contains two objects, the key being a "person" object, which has a firstname, lastname field etc, I want to print firstname, I don't see how this code would do that? Thanks for your time. – almost a beginner Oct 27 '15 at 02:10
  • 1
    @almostabeginner To be precise, this code prints all `Entry`'s in map, calling their `toString` method implicitly. If you want to print keys, or some field in key, you can do something like this: `codes.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).map(Map.Entry::getKey).map(Person::getLastName).forEach(System.out::println);` – AlexW Oct 29 '15 at 14:32
  • Thanks Vladimir S. for your help, respect :) – almost a beginner Oct 31 '15 at 03:13
  • How to use this with a logger ? I don't want to Syso ! Thanks :) – lmo Jan 22 '16 at 15:04
  • @lmo You can use any String consumer within `forEach`, e.g. `xxx.forEach(log::info)` – AlexW Jan 23 '16 at 16:05
5

the for loop of for(Map.Entry entry: codes.entrySet()) didn't work for me. Used Iterator instead.

Iterator<Map.Entry<String, String>> i = codes.entrySet().iterator(); 
while(i.hasNext()){
    String key = i.next().getKey();
    System.out.println(key+", "+codes.get(key));
}
akjoshi
  • 15,374
  • 13
  • 103
  • 121
psun
  • 615
  • 10
  • 13
  • 1
    This doesn't answer the question, because you're iterating on the original `HashMap`, which isn't sorted. – Dan Getz Jul 02 '15 at 01:39
5

you just need to use:

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

and replaces the ending square bracket of each key=value set with a new line.

David
  • 1,147
  • 4
  • 17
  • 29
ole scharling
  • 51
  • 1
  • 1
3

Java 8

map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(System.out::println);
bluehallu
  • 10,205
  • 9
  • 44
  • 61
2
  1. Create a TreeMap<String,String>
  2. Add each of the HashMap entries with the value as the key.
  3. iterate the TreeMap

If the values are nonunique, you would need a list in the second position.

bmargulies
  • 97,814
  • 39
  • 186
  • 310
  • Beautiful. Had to delete my answer :) –  Aug 31 '10 at 00:38
  • 6
    Not quite right... "Red-Black tree based implementation of the SortedMap interface. This class guarantees that the map will be in ascending key order, sorted according to the natural order for the key's class (see Comparable), or by the comparator provided at creation time, depending on which constructor is used." You'll have it sorted by the keys, not the values. – I82Much Aug 31 '10 at 00:39
1

You can use a list of the entry set rather than the key set and it is a more natural choice given you are sorting based on the value. This avoids a lot of unneeded lookups in the sorting and printing of the entries.

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());
   }
}
Dan Getz
  • 8,774
  • 6
  • 30
  • 64
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

the simplest and shortest code i think is this:

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

    for(Entry entry:caseList.entrySet()) {
        System.out.println("K: \t"+entry.getKey()+", V: \t"+entry.getValue());
    }
}
Tomek Szpakowicz
  • 14,063
  • 3
  • 33
  • 55
Eric
  • 460
  • 6
  • 15
-1

The simplest solution would be to use a sorted map like TreeMap instead of HashMap. If you do not have control over the map construction, then the minimal solution would be to construct a sorted set of keys. You don't really need a new map.

Set<String> sortedKeys = new TreeSet<String>();
sortedKeys.addAll(codes.keySet());

for(String key: sortedKeys){
    println(key  + ":" + codes.get(key));
}
aar
  • 322
  • 1
  • 7
-2

Try:

try
{
    int cnt= m.getSmartPhoneCount("HTC",true);      
    System.out.println("total count of HTC="+cnt);
}  
catch (NoSuchBrandSmartPhoneAvailableException e)
{
    // TODO Auto-generated catch 
    e.printStackTrace();
}
enb081
  • 3,831
  • 11
  • 43
  • 66
deeps
  • 1
-3
 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);
deeps
  • 1
  • 2
    Mind to [explain your solution](http://stackoverflow.com/help/how-to-answer) a bit? You might want to read [How Do I Write A Good Answer](http://stackoverflow.com/help/how-to-answer). – Markus W Mahlberg Apr 27 '15 at 12:32
  • Was this intended to be posted as an answer to a different question? If so, please delete it here. – Dan Getz Jul 02 '15 at 01:30
-3
while (itr.hasNext()) {
    Vehicle vc=(Vehicle) itr.next();
    if(vc.getVehicleType().equalsIgnoreCase(s)) {
        count++;
    }
}
luk2302
  • 55,258
  • 23
  • 97
  • 137
Roks
  • 1