Search code examples
javaalgorithmhashmapcountingtreemap

Counting the values of a map


The following map contains data of the form:

1946-01-12;13:00:00;0.3;G
1946-01-12;18:00:00;-2.8;Y
1946-01-13;07:00:00;-6.2;G
1946-01-13;13:00:00;-4.7;G

The dates are the keys.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.NavigableMap;
import java.util.TreeMap;

public class WeatherDataHandler {
    private NavigableMap<LocalDate, List<Weather>> weatherData =
            new TreeMap<>();
    
    public void loadData(String filePath) throws IOException {
        List<String> fileData =
                Files.readAllLines(Paths.get(filePath));
        for (String str : fileData) {
            List<String> parsed = parseData(str);
            LocalDate date = LocalDate.parse(parsed.get(0));
            LocalTime time = LocalTime.parse(parsed.get(1));
            double temperature = Double.parseDouble(parsed.get(2));
            String quality = parsed.get(3);
            Weather weather =
                    new Weather(date, time, temperature, quality);
            
            List<Weather> entries;
            entries = new ArrayList<Weather>();
            if (weatherData.get(date) == null) {
                entries.add(weather);
                weatherData.put(date, entries);
            } else {
                entries = weatherData.get(date);
                entries.add(weather);
            }
        }
    }
    
    private List<String> parseData(String str) {
        return Arrays.asList(str.split(";"));
    }
}

Now, I want to implement a method that counts the number of entries of every key, or in other words, the number of times every date occur in the list. It shall return all dates between two dates (that is user input) and the number of values of every key. I started with the following code

/**
 * Search for missing values between the two dates (inclusive) assuming there
 * should be 24 measurement values for each day (once every hour). Result is
 * sorted by date.
 */
public Map<LocalDate, Integer> missingValues(LocalDate dateFrom, LocalDate dateTo) {

    Map<LocalDate, Integer> counts = weatherData.subMap(dateFrom , dateTo)
            .values().stream()
            .flatMap(List::stream)
            .filter(p -> p.getValue()
            .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
    }
}

but I am having troubles with the filter and collectors method. How can I finish this?


Solution

  • Use Collectors.groupingBy to group by date of Weather class and Collectors.counting() to count the size of every group.

    Map<LocalDate, Long> counts = weatherData.subMap(dateFrom ,dateTo)
                                             .values()
                                             .stream()
                                             .flatMap(List::stream)
                            .collect(Collectors.groupingBy(p -> p.getDate(), Collectors.counting()));