Home > Blockchain >  Print a HashMap by sorting according to the size of the HashMap inside the HashMap
Print a HashMap by sorting according to the size of the HashMap inside the HashMap

Time:06-27

I have a HashMap inside a HashMap. I want to print the elements in the HashMap according to the size of elements in the inner HashMap. So the element with the highest number of elements should print first. I'm new to HashMaps and Currently got stuck here.

This is the HashMap and how I'm printing it:

Map<String, Map<String, Integer>> states = new ConcurrentHashMap<String, Map<String, Integer>>();

for(Entry<String, Map<String, Integer>> entry : states.entrySet()) {
        System.out.println("State:"   entry.getKey());
        Map<String, Integer> tempMap = entry.getValue();
        for(Entry<String, Integer> innerEntry : tempMap.entrySet()) {
            System.out.println("City:"   innerEntry.getKey()   " Count:"   innerEntry.getValue());
        }
        
        System.out.println();
    }

The output that I'm currently getting:

State:Texas
City:Austin Count:1

State:Hawaii
City:Honolulu Count:1
City:Kihei Count:1
City:Maui Count:1

State:California
City:Newport Beach Count:1

The output I need:

State:Hawaii
City:Honolulu Count:1
City:Kihei Count:1
City:Maui Count:1

State:Texas
City:Austin Count:1

State:california
City:Newport Beach Count:1

CodePudding user response:

Since ConcurrentHashMap makes no guarantees about ordering, you have to sort your map be getting entrySet and sort them then re-put into a LinkedHashMap

Map<String, Map<String, Integer>> sortedStates = new LinkedHashMap<String, Map<String, Integer>>();
states.entrySet().stream()
        .sorted(new Comparator<Map.Entry<String, Map<String, Integer>>>() {
            public int compare(Map.Entry<String, Map<String, Integer>> mapA, Map.Entry<String, Map<String, Integer>> mapB){
                return mapB.getValue().size() - mapA.getValue().size();
              }
            })
        .forEachOrdered(mapInner -> sortedStates.put(mapInner.getKey(), mapInner.getValue()));

CodePudding user response:

  1. create a size_map -> Map<Integer, List> size_map = new HashMap<Integer, List>();
  • This is to store store number of cities as key and states as the value. Note here states are stored in a list because multiple states can have same number of cities.
  1. Make a list (size_list) out of keys of map in point 1. (Keys are number of cities for different states). Order this list in descending order

  2. While iterating your "states" Hashmap, use size_list as a lookup and fetch the list of states with the current size from size_map HashMap. Basically use size_list as a lookup.

Note - this will increase your overhead and performance might not be great.

    Map<String, Map<String, Integer>> states = new ConcurrentHashMap<String, Map<String, Integer>>();

    //create size HashMap -- store number of cities as key and value would be list of states 
    Map<Integer, List<String>> size_map = new HashMap<Integer, List<String>>();

    for(Map.Entry<String, Map<String, Integer>> entry : states.entrySet())
    {
        int size = entry.getValue().size();
        String state = entry.getKey();
        if(size_map.containsKey(size))
        {
            List<String> retreived_list = size_map.get(size);
            retreived_list.add(state);
            size_map.put(size, retreived_list);
        }
        else
        {
            List<String> retreived_list = new ArrayList<String>();
            retreived_list.add(state);
            size_map.put(size, retreived_list);
        }
    }

    //create a list out of size_map keys and sort it in descending order
    List<Integer> size_list = new ArrayList<Integer>(size_map.keySet());
    Collections.sort(size_list, Collections.reverseOrder());

    //index will be current index in size_list, fetch states list from size_map and look for the same state in the original "state" hashmap
    int index =0;
    for(Map.Entry<String, Map<String, Integer>> entry : states.entrySet())
    {
        int current_size = size_list.get(index);
        List<String> states_list = size_map.get(current_size);

        for(String s : states_list)
        {
            System.out.println("State:"   s);
            Map<String, Integer> tempMap = states.get(s);
            for(Map.Entry<String, Integer> innerEntry : tempMap.entrySet()) {
                System.out.println("City:"   innerEntry.getKey()   " Count:"   innerEntry.getValue());
            }
        }
        index  ;
        System.out.println();
    }

CodePudding user response:

You can use Streams API for sorting before print it out:

Comparator<Entry<String, Map<String, Integer>>> entryComparator =
        Comparator.comparingInt((Entry<String, Map<String, Integer>> entryOne) -> entryOne.getValue().size());

    for(Entry<String, Map<String, Integer>> entry : states.entrySet().stream().sorted(entryComparator.reversed()).collect(
        Collectors.toList())) {
      System.out.println("State:"   entry.getKey());
      Map<String, Integer> tempMap = entry.getValue();
      for(Entry<String, Integer> innerEntry : tempMap.entrySet()) {
        System.out.println("City:"   innerEntry.getKey()   " Count:"   innerEntry.getValue());
      }

      System.out.println();
    }

CodePudding user response:

HashMap makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time. Using LinkedHashMap instead and that will look like:

Map sortedMap = new LinkedHashMap();
originalHashMap.entrySet().stream()
     .sorted(Comparator.comparingInt(e -> e.getValue().size()))
     .forEachOrdered(e -> sortedMap.put(e.getKey(), e.getValue()));

Now, expected sorted map is sortedMap

  • Related