Skip to content
Advertisement

Print the contents of a HashMap in sorted order according to the Size of each HashMap nested inside the given HashMap

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 got stuck.

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

Advertisement

Answer

HashMap is not capable of maintaining the order, therefore you can’t sort it.

You can dump the map contents into a list and sort it using a custom comparator. But there’s something that you’re missing – the way you’re structuring the data is wrong, state and cities that belong to that state are two pieces of information are closely related to each other. Using a map to combine them together is an abuse of collections, it makes your code rigid and unmaintainable.

Use the power of Objects

Your code doesn’t become object-oriented automatically because of the fact that you’re using an object-oriented language.

The correct approach would be to define State and City as classes and maintain a list of State objects instead of dealing with a nested map.

class State {
    private String name;
    private List<City> cities = new ArrayList<>();
    
    public State(String name) {
        this.name = name;
    }
    
    public void addCity(City city) {
        cities.add(city);
    }
    
    public boolean removeCity(City city) {
        return cities.remove(city);
    }
    
    public List<City> getCities() {
        return cities;
    }
    
    @Override
    public String toString() {
        return "State:" + name + "n" +
            cities.stream()
                .map(City::toString)
                .collect(Collectors.joining("n"))
            + "n";
    }
}

class City {
    private String name;
    private int count;
    
    public City(String name, int count) {
        this.name = name;
        this.count = count;
    }
    
    @Override
    public String toString() {
        return "City:" + name + " Count:" + count;
    }
}

That’s how you can use this classes in the client code:

public static void main(String[] args) {
    List<State> states = new ArrayList<>();
    State texas = new State("Texas");
    texas.addCity(new City("Austin", 1));
    
    State hawaii = new State("Hawaii");
    hawaii.addCity(new City("Honolulu", 1));
    hawaii.addCity(new City("Kihei", 1));
    hawaii.addCity(new City("Maui", 1));
    
    State california = new State("California");
    california.addCity(new City("Newport Beach", 1));
    
    Collections.addAll(states, texas, hawaii, california);
    
    states.sort(Comparator.<State>comparingInt(state -> state.getCities().size()).reversed());
    
    for (State state: states) {
        System.out.println(state);
    }
}

Output:

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
Advertisement