How to sort a Map in Java

In this article, we will show you few Java examples to sort a Map by its keys or by its values.

1. Sort a Map by Keys

To sort a Map by its keys, uses TreeMap, it sort Map keys automatically.

1.1 Review a “Map keys” in “String” example.

SortMapOnKeyStringExample.java
package com.mkyong;
 
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
 
public class SortMapOnKeyStringExample {
 
	public static void main(String[] args) {
 
		Map<String, String> unsortMap = new HashMap<String, String>();
		unsortMap.put("Z", "z");
		unsortMap.put("B", "b");
		unsortMap.put("A", "a");
		unsortMap.put("C", "c");
		unsortMap.put("D", "d");
		unsortMap.put("E", "e");
		unsortMap.put("Y", "y");
		unsortMap.put("N", "n");
		unsortMap.put("J", "j");
		unsortMap.put("M", "m");
		unsortMap.put("F", "f");
 
		System.out.println("Unsort Map......");
		printMap(unsortMap);
 
		System.out.println("\nSorted Map......");
		Map<String, String> treeMap = new TreeMap<String, String>(unsortMap);
		printMap(treeMap);
 
	}
 
	public static void printMap(Map<String, String> map) {
		for (Map.Entry<String, String> entry : map.entrySet()) {
			System.out.println("Key : " + entry.getKey() 
                                      + " Value : " + entry.getValue());
		}
	}
 
}

Output

Unsort Map......
Key : D Value : d
Key : E Value : e
Key : F Value : f
Key : A Value : a
Key : B Value : b
Key : C Value : c
Key : M Value : m
Key : N Value : n
Key : Y Value : y
Key : J Value : j
Key : Z Value : z
 
Sorted Map......
Key : A Value : a
Key : B Value : b
Key : C Value : c
Key : D Value : d
Key : E Value : e
Key : F Value : f
Key : J Value : j
Key : M Value : m
Key : N Value : n
Key : Y Value : y
Key : Z Value : z

1.2 Review a “Map keys” in “Integer” example.

SortMapOnKeyIntegerExample.java
package com.mkyong;
 
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
 
public class SortMapOnKeyIntegerExample {
 
	public static void main(String[] args) {
 
		Map<Integer, String> unsortMap = new HashMap<Integer, String>();
		unsortMap.put(10, "z");
		unsortMap.put(5, "b");
		unsortMap.put(6, "a");
		unsortMap.put(20, "c");
		unsortMap.put(1, "d");
		unsortMap.put(7, "e");
		unsortMap.put(8, "y");
		unsortMap.put(99, "n");
		unsortMap.put(50, "j");
		unsortMap.put(2, "m");
		unsortMap.put(9, "f");
 
		System.out.println("Unsort Map......");
		printMap(unsortMap);
 
		System.out.println("\nSorted Map......");
		Map<Integer, String> treeMap = new TreeMap<Integer, String>(
			new Comparator<Integer>() {
 
			@Override
			public int compare(Integer o1, Integer o2) {
				return o2.compareTo(o1);
			}
 
		});
		treeMap.putAll(unsortMap);
 
		printMap(treeMap);
 
	}
 
	public static void printMap(Map<Integer, String> map) {
		for (Map.Entry<Integer, String> entry : map.entrySet()) {
			System.out.println("Key : " + entry.getKey() 
                                      + " Value : " + entry.getValue());
		}
	}
 
}

Output

Unsort Map......
Key : 50 Value : j
Key : 1 Value : d
Key : 2 Value : m
Key : 99 Value : n
Key : 20 Value : c
Key : 5 Value : b
Key : 6 Value : a
Key : 7 Value : e
Key : 8 Value : y
Key : 9 Value : f
Key : 10 Value : z
 
Sorted Map......
Key : 99 Value : n
Key : 50 Value : j
Key : 20 Value : c
Key : 10 Value : z
Key : 9 Value : f
Key : 8 Value : y
Key : 7 Value : e
Key : 6 Value : a
Key : 5 Value : b
Key : 2 Value : m
Key : 1 Value : d

By default, it will sorts the “Integer” keys by ascending order, 0-10. In this example, we add a Comparator to TreeMap and make it sorts keys by descending order.

2. Sort a Map by Values

TreeMap is unable to sort the Map values, instead, we should use Comparator.

The overall idea is, converts the Map into a List, sorts the List by Comparator and put the sorted list back to a Map.

Map ---> List ---> Sort --> SortedList ---> Map

2.1 Review a Map values in “Integer” example.

SortMapOnValueIntegerExample.java
package com.hostingcompass.jobs;
 
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
 
public class SortMapOnValueIntegerExample {
 
	public static void main(String[] args) {
 
		Map<String, Integer> unsortMap = new HashMap<String, Integer>();
		unsortMap.put("z", 10);
		unsortMap.put("b", 5);
		unsortMap.put("a", 6);
		unsortMap.put("c", 20);
		unsortMap.put("d", 1);
		unsortMap.put("e", 7);
		unsortMap.put("y", 8);
		unsortMap.put("n", 99);
		unsortMap.put("j", 50);
		unsortMap.put("m", 2);
		unsortMap.put("f", 9);
 
		System.out.println("Unsort Map......");
		printMap(unsortMap);
 
		System.out.println("\nSorted Map......");
		Map<String, Integer> sortedMap = sortByComparator(unsortMap);
		printMap(sortedMap);
 
	}
 
	private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap) {
 
		// Convert Map to List
		List<Map.Entry<String, Integer>> list = 
			new LinkedList<Map.Entry<String, Integer>>(unsortMap.entrySet());
 
		// Sort list with comparator, to compare the Map values
		Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
			public int compare(Map.Entry<String, Integer> o1,
                                           Map.Entry<String, Integer> o2) {
				return (o1.getValue()).compareTo(o2.getValue());
			}
		});
 
		// Convert sorted map back to a Map
		Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
		for (Iterator<Map.Entry<String, Integer>> it = list.iterator(); it.hasNext();) {
			Map.Entry<String, Integer> entry = it.next();
			sortedMap.put(entry.getKey(), entry.getValue());
		}
		return sortedMap;
	}
 
	public static void printMap(Map<String, Integer> map) {
		for (Map.Entry<String, Integer> entry : map.entrySet()) {
			System.out.println("[Key] : " + entry.getKey() 
                                      + " [Value] : " + entry.getValue());
		}
	}
 
}

Output

Unsort Map......
[Key] : f [Value] : 9
[Key] : d [Value] : 1
[Key] : e [Value] : 7
[Key] : b [Value] : 5
[Key] : c [Value] : 20
[Key] : a [Value] : 6
[Key] : n [Value] : 99
[Key] : m [Value] : 2
[Key] : j [Value] : 50
[Key] : z [Value] : 10
[Key] : y [Value] : 8
 
Sorted Map......
[Key] : d [Value] : 1
[Key] : m [Value] : 2
[Key] : b [Value] : 5
[Key] : a [Value] : 6
[Key] : e [Value] : 7
[Key] : y [Value] : 8
[Key] : f [Value] : 9
[Key] : z [Value] : 10
[Key] : c [Value] : 20
[Key] : j [Value] : 50
[Key] : n [Value] : 99

Done. Your ideas are welcome.

References

  1. TreeMap JavaDoc
  2. LinkedHashMap JavaDoc
  3. Comparator JavaDoc
Tags :

About the Author

mkyong
Founder of Mkyong.com and HostingCompass.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

  • Soumyasanta Bhowmik

    Hello mkyong,

    I have used below and I am getting key as sorted way.

    Map<String, List> objNormalTemplateHashMap=new TreeMap<String, List>();

    Please let me know, is this correct way to do?

    Thanks , Soumyasanta Bhowmik.

  • Java

    Sorting TreeMap with key will not work when the key is more than 10. The result will not be in a soreted manner.

  • http://www.river2c.com Free Job Posting and CV or Resume download Job Portal

    It is very useful information in my one of functional part in my Project

  • andresrolo

    this is perfect.
    Thanks
    from colombia

  • Pingback: How to count duplicated items in Java List()

  • http://randomtechieblog.blogspot.com Mahendra

    Very good example but it will fail if you try using null as value.

  • Alex

    Why not to use SortedMap? It exists in the Java API since 1.2 version. There is no need to re-invent anything!

    • Daniel

      Because SortedMap orders by Keys, this implementation sorts by the values.

  • http://www.echidna-band.com Potney

    Thanks for the very nice piece of code :)

  • Balasubramaniyan Murugesan

    Very nice website thanks for ur work..

  • Pingback: ???Java??Map????? | Wenming's Blog()

  • Marian

    Nice man,
    Mine, very quick attempt without much thinking, after having a few beers:) :
    sortedValues = new TreeSet(unsortMap.values()).asList();
    HashMap sortedMap = new HashMap
    for (Object value : sortedValues) { //sorted iteration
    for ( Set entry : unsortMap.entrySet() {
    if (entry.getValue().equals(value) {
    sortedMap.put(entry.getKey(), entry.getValue());
    }
    }
    }

  • Pingback: Java: cómo ordenar un Map | ilikeblues()

  • Anonymous

    There’s no guarantee the posted implementation will work. Or work on every platform.

    The contract for a Map does not guarantee the ordering of its Map.Entry members.

    So, just because you sort the values and then put them back in the map in that order, there’s no contract guarantee that the collection returned from values() or an iteration of the entrySet() will be in that order.

    The replies that use TreeMap with a special comparator might work, but they defy the contract of TreeMap, which says the entries are sorted by KEY; wrap that TreeMap in a new class that makes an explicit contract to order its entries by value and hide all the implementation details inside.

    • http://www.mkyong.com mkyong

      Thanks for your sharing, So, do you have alternative way to sort a Map by ts value?

      • Anonymous

        why does one need to do this, I wonder… then I may have a solution…

        LinkedHashMap is a concrete class? I’ve never needed to do what is being described, so… ignorance is bliss… I stick to using Map as an interface and do not write code that requires a specific implementation.

        • Nan Shi

          A use case of a sorted map is that: 1. when u put pairs into a map, u want to remove or update on duplicated keys, i.e. keep keys uniq. 2. you need a sorted list, say then u can ask for the top 5 keys that have the bigger values. This is actually a very valuable and useful case.

      • cane

        I think, it possible to Sort a Map by values using Set instead of List.

        private static final Comparator&lt;Map.Entry&lt;String, String&gt;&gt; valueComparator = new Comparator&lt;Map.Entry&lt;String, String&gt;&gt;() {
        	@Override
        	public int compare(Map.Entry&lt;String, String&gt; e1,
        			Map.Entry&lt;String, String&gt; e2) {
        		//comparing by values, if it's equals, compare by keys
        		// in other case, entries with equals values will be removed
        		if(e1.getValue().equals(e2.getValue()))
        			return e1.getKey().compareTo(e2.getKey());
         
        		return (e1.getValue()).compareTo(e2.getValue());
        	}
        };
         
        private static Map&lt;String, String&gt; sortByComparator(
        			Map&lt;String, String&gt; unsortMap) {
         
        		// sorted set based on comparator
        		SortedSet&lt;Map.Entry&lt;String, String&gt;&gt; set = new TreeSet&lt;&gt;(
        				valueComparator);
        		set.addAll(unsortMap.entrySet());
         
        		// LinkedHashMap make sure order in which keys were inserted
        		Map&lt;String, String&gt; sortedMap = new LinkedHashMap&lt;&gt;();
        		for (Iterator&lt;Map.Entry&lt;String, String&gt;&gt; it = set.iterator(); it
        				.hasNext();) {
        			Map.Entry&lt;String, String&gt; entry = it.next();
        			sortedMap.put(entry.getKey(), entry.getValue());
        		}
        		return sortedMap;
        	}
    • TymTheEnchanter

      Isn’t that what the LinkedHashMap does? Provide a predictable iteration order based on input order?

  • Chris

    Take it to the next level and make it like TreeMap but on the values so whenever you insert it goes into the sorted by value spot.

  • http://www.japplis.com Anthony Goubard

    Here is a shorter version I’ve written that doesn’t use a list

    public static <K, V extends Comparable> Map sortByValues(final Map map) {
     
        Comparator valueComparator = new Comparator<K>() {
    	   public int compare(K k1, K k2) {
     
    	   int compare = ((String) map.get(k2)).compareTo((String) map.get(k1));
     
    	   if (compare == 0) {
    		   return 1;
    	   } else {
    		   return compare;
    	   }
        }  
       };
     
       Map sortedByValues = new TreeMap<K, V>(valueComparator);
       sortedByValues.putAll(map);
     
       return sortedByValues;
    }
    • http://www.mkyong.com mkyong

      Thanks for this non-list sorting example, but this put the map’s value sorted in descending order, can it be ascending as well?

      • http://www.japplis.com Anthony Goubard

        Yes inverse k1 and k2 in the comparator

    • Harikrishnan

      Still more shorter :) try this..

      TreeMap sortedByValues = new TreeMap(unsortedMap);

      sortedMap – map will be sorted by key.

  • Zemian Deng

    Few comments:
    1) The example is probably better named ValueSortedMap, to not confusing with existing java.util.SortedMap, which is by keys.

    2) Your example mixed with Java generics and then not using it all the way through. Very annoying. You should correctly typing the List and Map.Entry for example will save you from casting.

    3) Probably good to mention a great use case for this is where you use a Map model to display a HTML form (spring form) option list, and want to sort the listing values.

    4) If you are not going to have duplicated values in the map, consider using the commons-collections library, which provided TreeBidiMap just for this. You just call inverseBidiMap() to get a reversed map with values sorted as keys! But the library is not fitted with 1.5 generics though, minor thing consider you get all the implementation for free. :)

    • http://www.mkyong.com mkyong

      Really appreciated sharing your invaluable experience.

      • Nan Shi

        mkyong, you can probably use Eclipse instead of some geeky code editors, so you will see all those warnings and get it fixed before publishing your snippets.