Main Tutorials

Java 8 – How to sort a Map

sorting

Java 8 Stream examples to sort a Map, by keys or by values.

1. Quick Explanation

Steps to sort a Map in Java 8.

  1. Convert a Map into a Stream
  2. Sort it
  3. Collect and return a new LinkedHashMap (keep the order)

Map result = map.entrySet().stream()
	.sorted(Map.Entry.comparingByKey()) 			
	.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
	(oldValue, newValue) -> oldValue, LinkedHashMap::new));

P.S By default, Collectors.toMap will returns a HashMap

2. Sort by Keys

SortByKeyExample.java

package com.mkyong.test;

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

public class SortByKeyExample {

    public static void main(String[] argv) {

        Map<String, Integer> unsortMap = new HashMap<>();
        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("g", 50);
        unsortMap.put("m", 2);
        unsortMap.put("f", 9);

        System.out.println("Original...");
        System.out.println(unsortMap);

        // sort by keys, a,b,c..., and return a new LinkedHashMap
        // toMap() will returns HashMap by default, we need LinkedHashMap to keep the order.
        Map<String, Integer> result = unsortMap.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));


        // Not Recommend, but it works.
        //Alternative way to sort a Map by keys, and put it into the "result" map
        Map<String, Integer> result2 = new LinkedHashMap<>();
        unsortMap.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .forEachOrdered(x -> result2.put(x.getKey(), x.getValue()));

        System.out.println("Sorted...");
        System.out.println(result);
        System.out.println(result2);

    }

}

Output


Original...
{a=6, b=5, c=20, d=1, e=7, f=9, g=50, y=8, z=10, m=2, n=99}

Sorted...
{a=6, b=5, c=20, d=1, e=7, f=9, g=50, m=2, n=99, y=8, z=10}
{a=6, b=5, c=20, d=1, e=7, f=9, g=50, m=2, n=99, y=8, z=10}

3. Sort by Values

SortByValueExample.java

package com.mkyong.test;

package com.mkyong;

import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class SortByValueExample {

    public static void main(String[] argv) {

        Map<String, Integer> unsortMap = new HashMap<>();
        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("g", 50);
        unsortMap.put("m", 2);
        unsortMap.put("f", 9);

        System.out.println("Original...");
        System.out.println(unsortMap);

        //sort by values, and reserve it, 10,9,8,7,6...
        Map<String, Integer> result = unsortMap.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));

						
        //Alternative way
        Map<String, Integer> result2 = new LinkedHashMap<>();
        unsortMap.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                .forEachOrdered(x -> result2.put(x.getKey(), x.getValue()));

        System.out.println("Sorted...");
        System.out.println(result);
        System.out.println(result2);

    }
}

Output


Original...
{a=6, b=5, c=20, d=1, e=7, f=9, g=50, y=8, z=10, m=2, n=99}

Sorted...
{n=99, g=50, c=20, z=10, f=9, y=8, e=7, a=6, b=5, m=2, d=1}
{n=99, g=50, c=20, z=10, f=9, y=8, e=7, a=6, b=5, m=2, d=1}

4. Map<Object,Object>

The Stream can’t sort the Map<Object,Object> directly. To solve it, convert it into Map<String,String>, review below example.

Note
If you have better idea to sort it, do let me know.
DisplayApp.java

package com.mkyong;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

public class DisplayApp {

    public static void main(String[] args) {

        Properties properties = System.getProperties();
        // not easy to sort this
        Set<Map.Entry<Object, Object>> entries = properties.entrySet();

        LinkedHashMap<String, String> collect = entries.stream()
                //Map<String, String>
                .collect(Collectors.toMap(k -> (String) k.getKey(), e -> (String) e.getValue()))
                .entrySet()
                .stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));

        collect.forEach((k, v) -> System.out.println(k + ":" + v));

    }

}
Note
Not using Java 8? Try this classic way to sort a Map in Java.

References

  1. How to sort a Map in Java
  2. LinkedHashMap JavaDoc
  3. Collectors.toMap() JavaDoc
  4. More Fun with Wildcards
  5. Collections.sort() signature
  6. Difference between and in Java

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
26 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Thach
6 years ago

Map result = unsortMap.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));

I am sorry but what does it mean (oldValue, newValue) -> oldValue ?

karthik MANOHARAN
3 years ago
Reply to  mkyong

there is no way map should have duplicate key then why we are using (old value, new value)-> old value

Roshan
2 years ago

In this scenario, it is not much needed. However, M
kyong wanted to showcase all the available features of Collectors.toMap in an example. It would be useful when we use comparingByValue

Nicolas Garay
4 years ago
Reply to  mkyong

I think you should change the variables names, “oldValue” and “newValue” is really confusing.

rancho
5 years ago
Reply to  Thach

Map result = unsortMap.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue);
won’t cause any compile problems, but the keys might be duplicate, in which case throw
“java.lang.IllegalStateException: Duplicate key” exception.
by using extra arguments “(oldValue, newValue) -> oldValue, LinkedHashMap::new”
method will be overloaded as “R collect(Collector collector);”
this will make sure mergeFunction (oldValue, newValue) -> oldValue be passed in, and duplicate keys removed.

Tulasee
5 years ago

Reg : The Stream can’t sort the Map directly. To solve it, convert it into Map
for workaround use below line whenever you need sorting on map.
–> Map sortedMymap = new TreeMap((Comparator)(o1,o2)->{if(o1.getId()>o2.getId()) return -1;return 0;});

Note : it is completely key based.

I hope it helps 🙂

Rashmi
5 years ago

Really nice example programs, I love this site

Anton Balaniuc
6 years ago

Hi Mkyong,

Please note that is not recommended to use foreach to populate other collection. The collect operation is more preferable in this case.

unsortedMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue,
(e1,e2) -> e1, LinkedHashMap::new));

instead of

//sort by key, a,b,c…, and put it into the “result” map
unsortMap.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEachOrdered(x -> result.put(x.getKey(), x.getValue()));

Best Regards,
Anton

Shashank Tiwari
1 year ago
HashMap<Integer,String> hm=new HashMap();

hm.put(3,"INDIA");
hm.put(1, "JAPAN");
hm.put(2,"CHINA");
System.out.println(hm);


   List<String> st= hm.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.
           toMap(Map.Entry::getKey,Map.Entry::getValue,(oldValue,newValue)->oldValue,LinkedHashMap::new));

In the Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue, --- I get compilation error saying that Non-static method cannot be referenced from a static context .
 
are you not getting same compilation issue ? I am using Java 16 version .

Jon
1 year ago

I get different error, but on java 17 it’s not working for me.

Nagaraj
3 years ago

not enough explanation.

isaac michaan
3 years ago

Thanks! Very Helpfull!

Peng Peng
4 years ago

Properties properties = System.getProperties();
// not easy to sort this
Set entries = properties.entrySet();

LinkedHashMap collect = entries
.stream()
.sorted(Map.Entry.comparingByKey(Comparator.comparing(Object::toString)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));

Mayank
4 years ago

for custom objects, I was using below method and seems like it is working fine:

Foe e.g. Student class:

public class Student {
private int id;
private String name;
private int age;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

Sort by student id:

public Map getSortedMapCustomAsc(Map map){
LinkedHashMap collect = map.entrySet().stream()
.sorted(Map.Entry.comparingByValue((Comparator)(o1,o2)->{if(o1.getId()>o2.getId()) return 1;return 0;}))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
return collect;
}

Ramazan Karagöz
5 years ago

How can i sort according to UTF-8 in this way ?

Bhanuprasad
5 years ago

Hi mkyong,
just need small help in my scenario like
map(user0,value
user1,value
user2,value
passo,value
pass1,value
pass2,value
url0,value
url1,value
url2,value)

I want the output as
map(user0,value
pass0,value
url0,value
user1,value
pass1,value
url1,value
…..)
like this could you please help me with the logic.
I used tree map already which is not working as expected.

karthikeyan
6 years ago

How to handle null key/value here?

Nidhi
3 years ago
Reply to  mkyong

Hi Mkyong, i had a scenario where values of map is null and it is failing (oldvalue, newvalue) -> oldvalue, LinkedHashMap::new) logic. I can’t filter out the null values they are part of my final object and i am doing sorting based on Map key. can you please suggest

Anuj
3 years ago
Reply to  Nidhi

instead use nullsFirst() or nullsLast()
map.entrySet().stream().sorted(Map.Entry.comparingByKeys(Comparator.nullsFirst(Comparator.naturalOrder()))).collect(Entry::getKey, Entry:: getValue, (x, y) -> x, LinkedHashMap::new)

Hope this helps 🙂

Carol
6 years ago

Thanks, very clear.

Conor
7 years ago

Wow this is very powerful! Can you comment on the time complexity required to do such an operation? Your code is pretty self-explanatory but I am unsure about the underlying mechanisms Java is using to do the sorting.

ganesh bn
7 years ago

Please expline deeply

mkyong
7 years ago
Reply to  ganesh bn

The source code should be self-explanatory, which lines need to explain more?