Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Sort Maps in Java 8

I have a list of maps like below. I want to sort the maps inside the list in custom order in Java 8.

For Example, Below is the list of maps .

[{model=Ferrari},
{model=Tesla},
{model=Benz},
{model=Honda}]

If I sort the above list of maps using the below code, Its sorting in Alphabetical order.

l.sort(Comparator.comparing((Map<String,String> mp) -> mp.get("model")));

gives the output below.

[{model=Benz}, {model=Ferrari}, {model=Honda}, {model=Tesla}]

But I need to sort this map based on the order(Not Alphabetical Order) : Honda,Tesla,Benz, Ferrari

Is there a better approach we can achieve the custom sort in Java 8 ?

like image 744
sparker Avatar asked Nov 22 '17 14:11

sparker


People also ask

How do you create a custom sort in Java?

In order to sort Employee object on different criteria, we need to create multiple comparators e.g. NameComparator, AgeComparator, and SalaryComparator, this is known as custom sorting in Java. This is different from the natural ordering of objects, provided by the compareTo() method of java. lang.

Can we sort maps in Java?

Since Java 8, we can use the Stream API and lambda expressions to sort the map. All we need is to call the sorted method over the map's stream pipeline.


1 Answers

You should define your preferred order somewhere outside of this code. Put it into some kind of list and then transform it to Map of modelName -> index.

Map<String,Integer> modelOrder = .....

then, you can add one more lookup for getting ordinal for comparison.

l.sort(Comparator.comparing((Map<String,String> mp) ->
    modelOrder.get(mp.get("model"))));

This will explode in your face if unknown model is ever encountered. You can do quick fix by something like

l.sort(Comparator.comparing((Map<String,String> mp) -> 
    modelOrder.getOrDefault(mp.get("model"),Integer.MAX_VALUE)));

to put unknown models at the very end, but they won't be sorted between themselves (so even same unknown model might be interlaced by other unknown ones).

Edit:

As people suggested in comments, it can be solved nicely with .thenComparing

l.sort(Comparator
    .comparing((Map<String,String> mp) -> modelOrder.getOrDefault(mp.get("model"),Integer.MAX_VALUE))
    .thenComparing((Map<String,String> mp) -> mp.get("model")));
like image 132
Artur Biesiadowski Avatar answered Oct 02 '22 01:10

Artur Biesiadowski