Search code examples
javajava-8hashmapjava-9

What is a proper way to reverse the order of nested java Maps


I'm trying to reverse the order of a nested Map.

As there is no built-in function in Map to reverse the order and I'm out of time. I tried several available methods of reversing the order posted by devs but nothing worked and also I didn't see any error. I don't know what's wrong with the code probably because I've not used Map that much and I'm relatively new to java.

Here is the structure of the map Map<String, HashMap<String, Object>> playersDataMap = new HashMap<> ();

And these are a couple of methods I copied from a website but none of them worked. It always returns me the with the same order.

    public static <K extends Comparable, V> Map<K,V> sortByKeys(Map<K,V> map)
    {
        Map<K, V> treeMap = new TreeMap<>(new Comparator<K>() {
            @Override
            public int compare(K a, K b) {
                return b.compareTo(a);
            }
        });

        treeMap.putAll(map);

        return treeMap;
    }

    public static <K, V> Map<K,V> sortByTreeMap(Map<K,V> unsortedMap)
    {
        // construct a TreeMap from given Map and return a reverse order
        // view of the mappings contained in this map
        return new TreeMap<>(unsortedMap).descendingMap();
    }

I also tried changing the HashMap to LinkedHashMap but no success, same results.

Please let me know what is wrong with the code. I'm really out of time otherwise I would have read the docs of Maps before posting or even implementation. Your help will be greatly appreciated. thanks

Here is the example of what I'm trying to implement

Map<String, HashMap<String, Object>> playersDataMap = new LinkedHashMap<> ();
for (int i = 1; i < 40; i++)
{
    HashMap<String, Object> playerMap = new HashMap<> ();
    playerMap.put ("name", "abc"+i);
    playerMap.put ("pointsScored", i * 10);
    playersDataMap.put ("x"+i, playerMap);
}


Map<String, HashMap<String, Object>> inversedPlayerDataMap = new LinkedHashMap<>();
inversedPlayerDataMap = new TreeMap<>(Comparator.reverseOrder());
inversedPlayerDataMap.putAll(playersDataMap);

for (Map.Entry<String, HashMap<String, Object>> player : inversedPlayerDataMap.entrySet ())
{
    System.out.printf ("Debug: player key: %s playerValueScore: %s \n", player.getKey (), player.getValue ().get("pointsScored"));
}

Results: "Debug: player key: x9 pointsScored: 90" "Debug: player key: x390 pointsScored: 390" "Debug: player key: x30 pointsScored: 30" ...

Expected output: "Debug: player key: x390 pointsScored: 390" "Debug: player key: x380 pointsScored: 380" ...


Solution

  • Both the above answers worked but to some extent. They didn't work on a mixed string.

    So what I did is replaced the HashMap to linkedHashMap. Then I added the keySet of that Map to newly created List of strings and reversed it using Collections.reverse then iterated through that list and added the reserved order into a new Map.

    Here is the code of my invert function.

    Important, the argument i passed as a playersDataMap is a linkedHashMap. For further explanation on LinkedHashMap please go to the following link https://beginnersbook.com/2013/12/linkedhashmap-in-java/. thanks!

    public static Map<String, HashMap<String, Object>> invertMapUsingList (Map<String, HashMap<String, Object>> playersDataMap)
    {
            Map<String, HashMap<String, Object>> inversedPlayerDataMap = new LinkedHashMap<> ();
            List<String> reverseOrderedKeys = new ArrayList<String>(playersDataMap.keySet());
            Collections.reverse(reverseOrderedKeys);
            for (String key : reverseOrderedKeys)
            {
                inversedPlayerDataMap.put (key, playersDataMap.get(key));
            }
    
            return inversedPlayerDataMap;
    }