简体   繁体   English

将数据从文本文件存储到 hashmap 而不是列表

[英]Storing data from text file to hashmap instead of list

The following program reads and stores data from a text file of the form以下程序从表单的文本文件中读取和存储数据

1946-01-12;13:00:00;0.3;G
1946-01-12;18:00:00;-2.8;G
1946-01-13;07:00:00;-6.2;G
1946-01-13;13:00:00;-4.7;G
1946-01-13;18:00:00;-4.3;G
1946-01-14;07:00:00;-1.5;G
1946-01-14;13:00:00;-0.2;G

to an array list.到数组列表。 Then I store the weather object in another class.然后我将天气 object 存储在另一个 class 中。 The first method calculates average temperature between two dates that is user input and the second method calculates the percentage of "G":s between the two dates.第一种方法计算用户输入的两个日期之间的平均温度,第二种方法计算两个日期之间“G”:s 的百分比。

/**
 * Provides methods to retrieve temperature data from a weather station file.    
 */
public class WeatherDataHandler {
        private List<Weather> weatherData = new ArrayList<>();

        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);
                    weatherData.add(weather);       
                }
            }
    
            private List<String> parseData(String s) {
                return Arrays.asList(s.split(";"));
            }
        /**
         * Search for average temperature for all dates between the two dates (inclusive).
         * Result is sorted by date.
         */
        public Map<LocalDate, Double> avarageTemperatures(LocalDate dateFrom, LocalDate dateTo) {
            Map<LocalDate, Double> Averagetemperature = weatherData.stream().filter(weather -> !weather.getDate().isAfter(dateTo) && !weather.getDate().isBefore(dateFrom))
                    .collect(Collectors.groupingBy(Weather::getDate,
                            Collectors.averagingDouble(Weather::getTemperature)));
                    
            return Averagetemperature;}
    
        /**
         * Search for percentage of approved values between the two dates (inclusive).
         */
        public Double approvedValues(LocalDate dateFrom, LocalDate dateTo) {
            double percentageApproved = weatherData.stream().filter(weather -> !weather.getDate().isAfter(dateTo) && !weather.getDate().isBefore(dateFrom))
                    .mapToInt(obj -> obj.getQuality().equals("G") ? 1 : 0)
                    .summaryStatistics()
                    .getAverage();
            
            return percentageApproved;
        }   
    }

Now, instead of implementing maps to the methods I would like to store the data from the file to a hashmap instead of a list (for efficiency).现在,我不想将映射到方法,而是将文件中的数据存储到 hashmap 而不是列表(为了提高效率)。 Is there any easy ways to do this without having to redo the methods completely?有没有简单的方法可以做到这一点而不必完全重做这些方法? I tried this:我试过这个:

    public class WeatherDataHandler {
        public void loadData1(String filePath) throws IOException {
        List<String> fileData = Files.readAllLines(Paths.get(filePath));
        Map<LocalDate, List<Weather>> weatherData = new HashMap<LocalDate,List<Weather>>();{
    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(";"));
        }

But how can I access the entries of the map in the methods?但是如何在方法中访问 map 的条目?

A hash map will not work for your use case. hash map 不适用于您的用例。 HashMap helps you find the matching value, given a key. HashMap 帮助您找到匹配的值,给定一个键。 For example, you could make a HashMap that gives you the matching weather data given one date.例如,您可以制作一个 HashMap,它为您提供给定日期的匹配天气数据。 But, you can't use a HashMap to answer the query "give me all weather data between these two dates" without iterating over the date range.但是,您不能使用 HashMap 来回答查询“给我这两个日期之间的所有天气数据”而不迭代日期范围。 And that's what you need for your avarageTemperatures and approvedValues methods.这就是您的avarageTemperaturesapprovedValues方法所需要的。

What you could use instead, is TreeMap .您可以使用的是TreeMap It will require changing your program in a couple of places.这将需要在几个地方更改您的程序。

The variable declaration:变量声明:

private List<Weather> weatherData = new ArrayList<>();

Has to become:必须变成:

private NavigableMap<LocalDate, List<Weather>> weatherData = new TreeMap<>();

This is a "map from date to list of weather data" because there are more than one data item per date.这是一张“从日期到天气数据列表的地图”,因为每个日期有多个数据项。 If you can change that, it would be simpler.如果你能改变它,它会更简单。

Next, instead of using weatherData.add(weather) you need to use:接下来,您需要使用以下命令,而不是使用weatherData.add(weather)

weatherData.computeIfAbsent(date, key -> new ArrayList<>()).add(weather);

Again, this is more complicated because there may be more than one item per date.同样,这更复杂,因为每个日期可能有多个项目。

Lastly, where you access the data through iteration:最后,您通过迭代访问数据的位置:

weatherData.stream().filter(weather -> !weather.getDate().isAfter(dateTo) && !weather.getDate().isBefore(dateFrom))

You would leverage the subMap method instead, which looks up a key range directly:您将改用subMap方法,该方法直接查找键范围:

weatherData.subMap(dateFrom, dateTo).values().stream().flatMap(List::stream)

HashMaps work on Key Value pairs. HashMaps 适用于键值对。 It's not possible for you to simply store in the values through the entire text file without first splitting and then iteratively mapping them together.您不可能在不先拆分然后迭代地将它们映射在一起的情况下简单地将值存储在整个文本文件中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM