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