Home > Net >  How to sum values in a map efficiently within java
How to sum values in a map efficiently within java

Time:08-17

DATA

enter image description here

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"?

  • Related