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