DATA
CountryInfo
public class CountryInfo {
private String country;
private String countryCode;
private String currency;
@Id
private String state;
private String stateCode;
private String statePopulation;
public HashMap<String, Integer> getAllCountryPopulations(){
List<CountryInfo> countries = countrySqlRepository.findAll();
HashMap<String, Integer> populations = new HashMap<>();
Integer sumOfPopulation = 0;
HashSet<String> set = new HashSet<String>();
for(int i=0; i<countries.size(); i ){
CountryInfo countryInfo = countries.get(i);
set.add(countryInfo.getCountryCode());
if(set.contains(countryInfo.getCountryCode())){
sumOfPopulation = Integer.parseInt(countryInfo.getStatePopulation().replaceAll(",", ""));
}
populations.put(countryInfo.getCountryCode(), sumOfPopulation);
}
return populations;
}
I am trying to return the sum of values for a given map on unique country codes. Instead of returning the corresponding sum for each key in the set I am getting the sum of all values within the set.
Example:
{America: 4329392, Canada: 13025402}
Should be
{America: 4329392, Canada: 8721010}
How do I fix my logic here?
Thanks in advance.
CodePudding user response:
In your logic, the problem is
Integer sumOfPopulation = 0;
should be defined inside your for loop as it will be different for each country.
Off-topic, you don't even need a set, a single HashMap will work here.
final List<CountryInfo> countries = countrySqlRepository.findAll();
final HashMap<String, Integer> populations = new HashMap<>();
for (final CountryInfo countryInfo : countries) {
final int sum = populations.getOrDefault(countryInfo.getCountryCode(), 0);
final int population = Integer.parseInt(countryInfo.getStatePopulation().replaceAll(",", ""));
populations.put(countryInfo.getCountryCode(), population sum);
}
return populations;
CodePudding user response:
To calculate the total population of cities that belong to the same country, you don't need anything but the Map
itself.
Variable sumOfPopulation
, as well as Set
are redundant. And also if
-statement checking whether a particular code is present in the set after it has been added on the previous line.
You can use Java 8 method merge()
to implement this logic:
public Map<String, Integer> getAllCountryPopulations() {
Map<String, Integer> populationByCountry = new HashMap<>();
for (CountryInfo country: countrySqlRepository.findAll()) {
populationByCountry.merge(country.getCountryCode(),
Integer.parseInt(country.getStatePopulation().replaceAll(",", "")),
Integer::sum);
}
return populationByCountry;
}
The same can be done in a more concise way using Stream API.
For that we can use collector groupingBy()
in conjunction with collector summingInt()
as a downstream.
public Map<String, Integer> getAllCountryPopulations() {
return countrySqlRepository.findAll().stream()
.collect(Collectors.groupingBy(
CountryInfo::getCountryCode,
Collectors.summingInt(countryInfo -> Integer.parseInt(countryInfo.getStatePopulation().replaceAll(",", "")))
));
}
Sidenote: don't use concrete classes like HahsMap
as types in your code, leverage abstractions instead - write your code against interfaces. See What does it mean to "program to an interface"?