The actual application scenario of Map sorting

As we know, Map is different from List in that it is unordered. However, in our actual work, some business scenarios require maps to be arranged and combined in a certain order. Some need to be sorted by keys, while others need to be sorted by value. For example, we now return a Map that encapsulates the data we need. Its value is unordered, but we now need to order the Map in ascending or descending order to return the data we want. How do we do that? Further complicating matters is how to achieve the sort we need if the Map is multi-nested.

1. Button sequencing

As we know, TreeMap is the ascending order of keys by default. If you want to sort the values of the Map by keys, you can use TreeMap directly. Let’s look at an example in practice.

    @Test
    public void TestTreeMapKeyAsc() {
        Map<String, String> treeMap = new TreeMap<String, String>();
        treeMap.put("2"."mad");
        treeMap.put("3"."kitty");
        treeMap.put("1"."cherry");
        treeMap.put("4"."jack");
        System.out.println(treeMap);
    }
Copy the code

The output

{1=cherry, 2=mad, 3=kitty, 4=jack}
Copy the code

Compare (T o1,To2) public compare(T o1,To2) public compare(T o1,To2) This method returns a negative integer, 0, or positive integer less than, equal to, or greater than o2, based on the first argument o1. Let’s look at the implementation of descending order

@Test
    public void TestTreeMapKeyDesc() {
        Map<String, String> treeMap = new TreeMap<String, String>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                returno2.compareTo(o1); }}); treeMap.put("2"."mad");
        treeMap.put("3"."kitty");
        treeMap.put("1"."cherry");
        treeMap.put("4"."jack");
        System.out.println(treeMap);
    }
Copy the code

The output

{4=jack, 3=kitty, 2=mad, 1=cherry}
Copy the code

TreeMap sort: TreeMap sort: TreeMap sort: TreeMap sort: TreeMap sort: TreeMap sort: TreeMap sort: TreeMap sort: TreeMap sort: TreeMap sort: TreeMap sort: TreeMap sort That is, we convert our HashMap to a List and then sort it. Source:

  @SuppressWarnings({"unchecked"."rawtypes"})
    public static <T> void sort(List<T> list, Comparator<? super T> c) {
        Object[] a = list.toArray();
        Arrays.sort(a, (Comparator)c);
        ListIterator<T> i = list.listIterator();
        for(int j=0; j<a.length; j++) { i.next(); i.set((T)a[j]); }}Copy the code

The code implements HashMap keystroke sorting (descending) with similar ascending logic.

   @Test
    public void TestHashMapKeyDesc() {
        Map<String, String> map = new HashMap<String, String>();
        map.put("2"."mad");
        map.put("3"."cherry");
        map.put("1"."kitty");
        map.put("4"."jack"); System.out.println(map); List<Map.Entry<String,String>> list=new ArrayList<Map.Entry<String, String>>(map.entrySet()); Collections.sort(list, new Comparator<Map.Entry<String, String>>() { @Override public int compare(Map.Entry<String, String> o1, map. Entry<String, String> O2) {// In descending orderreturno2.getKey().compareTo(o1.getKey()); // sort in ascending orderreturno1.getkey().compareTo(o2.getKey()); }}); map=new LinkedHashMap<String,String>();for(Map.Entry<String,String> mapping:list){
            System.out.println(mapping.getKey()+":"+mapping.getValue());
            map.put(mapping.getKey(),mapping.getValue());
        }
        System.out.println(map);
    }
Copy the code

After sorting, we need to redefine the Map as LinkedHashMap, which is sorted in the order of insertion. If it is a HashMap, it will be sorted in the same order, which is invalid. Output result:

{1=kitty, 2=mad, 3=cherry, 4=jack}
4:jack
3:cherry
2:mad
1:kitty
{4=jack, 3=cherry, 2=mad, 1=kitty}
Copy the code

2. Sort by value

Sort by value (TreeMap); sort by value (TreeMap); sort by value (TreeMap); sort by value (TreeMap);

@Test
public void TestTreeMapValueAsc() {
        Map<String, String> treeMap = new TreeMap();
        treeMap.put("mad"."2");
        treeMap.put("kitty"."3");
        treeMap.put("cherry"."1");
        treeMap.put("jack"."4");
        List<Map.Entry<String, String>> list = new ArrayList<Map.Entry<String, String>>(treeMap.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                returno1.getValue().compareTo(o2.getValue()); }});for(Map.Entry<String,String> mapping:list){
            System.out.println(mapping.getKey()+":"+mapping.getValue()); }}Copy the code

Output result:

cherry:1
mad:2
kitty:3
jack:4
Copy the code

The implementation of HashMap is almost the same as TreeMap, except that they are of different types and will not be demonstrated here.

3. Complex multiple sorting of values

The examples we gave above are the most basic ideas and examples, but in practice they are far from that simple. First of all, since the data is taken out and encapsulated from the DAO database layer, we actually process the data we need in the Service layer. So here we use the most primitive way to encapsulate similar Map data.


        Map<String, Object> resultMap = new HashMap<String, Object>();
        Map<String, String> dataMap = new HashMap<>();
        Map<String,String> dataMap1=new HashMap<>();
        Map<String,String> dataMap2=new HashMap<>();
        Map<String,String> dataMap3=new HashMap<>();
        dataMap.put("faultRate"."0.28%");
        dataMap.put("faultNum"."1");
        dataMap.put("faultTime"."1965");
        resultMap.put(Bill gate, dataMap);

        dataMap1.put("faultRate"."11.71%");
        dataMap1.put("faultNum"."3");
        dataMap1.put("faultTime"."80923");
        resultMap.put("Log printer",dataMap1);

        dataMap2.put("faultRate"."12.50%");
        dataMap2.put("faultNum"."5");
        dataMap2.put("faultTime"."86400");
        resultMap.put("Banknote movement",dataMap2);

        dataMap3.put("faultRate"."17.20%");
        dataMap3.put("faultNum"."Seven");
        dataMap3.put("faultTime"."86400");
        resultMap.put("Fingerprint reader",dataMap3);
Copy the code

Let’s look at the data structure of the resulting map:

FaultRate =0.28%, faultNum=1, faultTime=1965, faultRate=11.71%, faultNum=3, faultTime=80923, FaultRate =12.50% faultNum=5 faultTime=86400 fingerprint ={faultRate=17.20% faultNum=7 faultTime=86400}}Copy the code

Our current business requirement is to arrange the data in faultRate order from highest to lowest (if faultNum or faultTime, similar logic), i.e

{fingerprint ={faultRate=17.20%, faultNum=7, faultTime=86400} FaultTime =86400} faultRate=11.71%, faultNum=3, faultTime=80923} faultRate=0.28%, faultNum=1, faultTime=1965}}Copy the code

So how do you deal with this? In fact, we carefully observe the Map data structure, generally speaking, is to use the value of a key in the inner Map to sort the outer Map, the so-called all changes are the same, it is the most critical or Map value sorting problem, so we still use the method of value sorting to deal with, that is, through the outer Map to extract the inner Map, Then take out its value to sort.

  List<Map.Entry<String,Object>> list=new ArrayList<Map.Entry<String, Object>>(resultMap.entrySet());
       Collections.sort(list, new Comparator<Map.Entry<String, Object>>() {
           @Override
           public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
               Map<String, String> o1Map = (Map<String, String>) o1.getValue();
               Map<String, String> o2Map = (Map<String, String>) o2.getValue();
               Double f1 = Double.valueOf(o1Map.get("faultRate").replace("%".""));
               Double f2 = Double.valueOf(o2Map.get("faultRate").replace("%".""));
               returnf2.compareTo(f1); }});Copy the code

In this way, we can achieve the above business requirements, is not very simple ~ finally put the complete code posted for your reference:

@Test
    public void TestMultipleMapValueSort() {
    
        Map<String, Object> resultMap = new HashMap<String, Object>();
        Map<String, String> dataMap = new HashMap<>();
        Map<String,String> dataMap1=new HashMap<>();
        Map<String,String> dataMap2=new HashMap<>();
        Map<String,String> dataMap3=new HashMap<>();
        dataMap.put("faultRate"."0.28%");
        dataMap.put("faultNum"."1");
        dataMap.put("faultTime"."1965");
        resultMap.put(Bill gate, dataMap);

        dataMap1.put("faultRate"."11.71%");
        dataMap1.put("faultNum"."3");
        dataMap1.put("faultTime"."80923");
        resultMap.put("Log printer",dataMap1);

        dataMap2.put("faultRate"."12.50%");
        dataMap2.put("faultNum"."5");
        dataMap2.put("faultTime"."86400");
        resultMap.put("Banknote movement",dataMap2);

        dataMap3.put("faultRate"."17.20%");
        dataMap3.put("faultNum"."Seven");
        dataMap3.put("faultTime"."86400");
        resultMap.put("Fingerprint reader",dataMap3);
        System.out.println("Before sorting :");
       for (Map.Entry<String,Object> entry:resultMap.entrySet()){
           System.out.println(entry);
       };

       List<Map.Entry<String,Object>> list=new ArrayList<Map.Entry<String, Object>>(resultMap.entrySet());
       Collections.sort(list, new Comparator<Map.Entry<String, Object>>() {
           @Override
           public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
               Map<String, String> o1Map = (Map<String, String>) o1.getValue();
               Map<String, String> o2Map = (Map<String, String>) o2.getValue();
               Double f1 = Double.valueOf(o1Map.get("faultRate").replace("%".""));
               Double f2 = Double.valueOf(o2Map.get("faultRate").replace("%".""));
               returnf2.compareTo(f1); }}); Map<String, Object> sortMap = new LinkedHashMap<String, Object>();for (Map.Entry<String, Object> map : list) {
            sortMap.put(map.getKey(), map.getValue());
        }
        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");
        System.out.println("After sorting :");
        for (Map.Entry<String,Object> entry:sortMap.entrySet()){
            System.out.println(entry);
        };
Copy the code

Output result:

Before ordering: FaultRate =0.28%, faultNum=1, faultTime=1965 FaultTime =80923 faultTime= {faultRate=12.50%, faultNum=5, faultTime=86400} Fingerprint ={faultRate=17.20%, faultNum=7, FaultTime = 86400} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - sorted: Fingerprint ={faultRate=17.20%, faultNum=7, faultTime=86400} FaultTime =86400} faultRate=11.71%, faultNum=3, faultTime=80923} faultRate=0.28%, faultNum=1, faultTime=1965Copy the code