Schadenfreude
Schadenfreude

Reputation: 1910

Sorting a Map by key using values from another Map

I know there are a lot of similar questions, but I think my case is quite special, and I haven't really found a proper answer that helps me, so here it goes.

I have a Map<Integer,List<String>> with the Integer being a kind of grouping by type and the Strings list being the elements in that type. Each element in a type can have an order value assigned to it (which is not saved in the List by default), so I've made a Map<Integer, List<Integer>> which consists of the type as key and an element order list as values.

I want to sort the 1st Map by keys, but the values of those keys should be the lowest value from the List for the same key in the 2nd Map. I'm trying to do this by using Collections.sort() with a custom Comparator, but I'm a bit lost as to how exactly to achieve that. Here's the unfinished Comparator code:

 private class sortComparator implements Comparator {

    private Map<Integer, List<String>> grouped = null;
    private Map<Integer, List<Integer>> sortOrder = null;

    public sortComparator(Map<Integer, List<String>> grouped, Map<Integer, List<Integer>> sortOrder){
        this.grouped = grouped;
        this.sortOrder = sortOrder;
    }

    @Override
    public int compare(Object o1, Object o2) {

        return 0;
    }
    //get the lowest value from the values connected to a key
    private Integer sortGroups(Map<Integer,List<Integer>> sortOrder, Integer key){
        List<Integer> calcTypeOrder = sortOrder.get(key);
        Iterator orderIterator = calcTypeOrder.iterator();
        Integer firstElement;

        Collections.sort(calcTypeOrder);
        if (orderIterator.hasNext()){
            firstElement = (Integer)orderIterator.next();
        } else firstElement = 0;
        return firstElement;
    }
}

I'm quite uncertain how exactly to procede or if I'm even on the right track. I hope I was able to explain what I'm trying to do.
EDIT: More explanations as requested:

Map<Integer, List<String>> grouped
//Map<Type, List<ElementNames>>
//consists of elements, which look like this
Map.EntrySet<13, List<Template 1, Template 2>> //1st entry
Map.EntrySet<24, List<Something, Something Else>> //2nd entry
Map.EntrySet<1, List<Example, Example, Example>> //3rd entry
Map.EntrySet<35, List<More Things>> //4th entry

That information doesn't help me order the map, however I can get an ordered property from the database, which is set for Template 1 and Template 2 (in the current case). So I make another Map, with those entries:

Map<Integer, List<Integer>> sorted
//Map<Type, List<ElementOrder>>
//consists of elements, which look like this
Map.EntrySet<13, List<3, 4>> //1st entry
Map.EntrySet<24, List<1, 2>> //2nd entry
Map.EntrySet<1, List<6, 7, 8>> //3rd entry
Map.EntrySet<35, List<5>> //4th entry 

So basically I want the order in the 1st Map to be based on the values in the 2nd Map. In the current case, the lowest value for the 2nd EntrySet's values is 1, and the lowest value for the 1st EntrySet's values is 3, meaning that in the 1st Map, they have to switch places. Here's how it should look after the sort. Keep in mind that I've got both maps with all their entries before I start sorting, and their key/value pairs are equal, because they refer to properties of entries in a database.

Map<Integer, List<String>> groupedAfterSort
//Map<Type, List<ElementNames>>
//consists of elements, which look like this
Map.EntrySet<24, List<Something, Something Else>> //1st entry
Map.EntrySet<13, List<Template 1, Template 2>> //2nd entry
Map.EntrySet<35, List<More Things>> //3rd entry
Map.EntrySet<1, List<Example, Example, Example>> //4th entry

Upvotes: 0

Views: 1415

Answers (1)

Syam S
Syam S

Reputation: 8499

This should be simple. Just create a custom comparator and refer to the sort order list. For example the sortMap method will do what you are looking for.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;


public class MapSorter2 {

    public static void main(String[] args) {
        Map<Integer, List<String>> grouped = new HashMap<Integer, List<String>>();
        grouped.put(13, new ArrayList<String>() {{ add("Template 1"); add("Template 2"); }});
        grouped.put(24, new ArrayList<String>() {{ add("Something"); add("Something Else"); }});
        grouped.put(1, new ArrayList<String>() {{ add("Example"); add("Example"); add("Example"); }});
        grouped.put(35, new ArrayList<String>() {{ add("More Things"); }});

        Map<Integer, List<Integer>> sorted = new HashMap<Integer, List<Integer>>();
        sorted.put(13, new ArrayList<Integer>() {{ add(3); add(4); }});
        sorted.put(24, new ArrayList<Integer>() {{ add(1); add(2); }});
        sorted.put(1, new ArrayList<Integer>() {{ add(6); add(7); add(8); }});
        sorted.put(35, new ArrayList<Integer>() {{ add(5); }});

        Map<Integer, List<String>> sortedGrouped = sortMap(grouped, sorted);
        System.out.println(sortedGrouped);
    }

    private static Map<Integer, List<String>> sortMap(
            Map<Integer, List<String>> unsortedMap, Map<Integer, List<Integer>> sortOrder) {

        List<Entry<Integer, List<String>>> list = new LinkedList<Entry<Integer, List<String>>>(
                unsortedMap.entrySet());

        Collections.sort(list,
                new Comparator<Entry<Integer, List<String>>>() {

                    @Override
                    public int compare(Entry<Integer, List<String>> o1,
                            Entry<Integer, List<String>> o2) {
                        Integer key1 = o1.getKey();
                        Integer key2 = o2.getKey();
                        Integer sortObj1 = sortOrder.get(key1).get(0);
                        Integer sortObj2 = sortOrder.get(key2).get(0);
                        return sortObj1.compareTo(sortObj2);
                    }
                });

        Map<Integer, List<String>> sortedMap = new LinkedHashMap<Integer, List<String>>();
        for(Entry<Integer, List<String>> item : list){
            sortedMap.put(item.getKey(), item.getValue());
        }
        return sortedMap;
    }

}

Upvotes: 3

Related Questions