【问题标题】:Counting the values of a map计算地图的值
【发布时间】:2020-10-30 10:27:55
【问题描述】:

以下地图包含表格的数据:

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

日期是关键。

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(";"));
    }
}

现在,我想实现一个方法来计算每个键的条目数,或者换句话说,每个日期在列表中出现的次数。它应返回两个日期之间的所有日期(即用户输入)和每个键的值的数量。我从以下代码开始

/**
 * 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()));
    }
}

但我在使用过滤器和收集器方法时遇到了问题。我怎样才能完成这个?

【问题讨论】:

    标签: java algorithm hashmap counting treemap


    【解决方案1】:

    使用Collectors.groupingByWeather 班级的日期分组,使用Collectors.counting() 计算每个组的大小。

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

    【讨论】:

      【解决方案2】:

      您实际上需要的是按日期分组作为地图的关键元素。在值中,您希望每个键出现了多少次。

      为此,您必须在收集地图时使用Collectors.groupingBy。对于价值,它只是Collectors.counting()。详情请查看下方代码 sn-p:

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

      【讨论】:

        【解决方案3】:

        由于您使用流来简化代码,您可能还需要执行以下操作。

        而不是做

            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);
            }
        

        你可以这样做

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

        它说如果键date 不存在,则输入一个新的ArrayList 作为值。无论如何,请返回value。由于该值是刚刚输入或已经存在的list,因此您可以简单地将weather 实例添加到列表中。

        编译器已经知道列表的类型,因为它是从您的 NavigableMap 实例派生的。

        如果你想先检查一下,试试这个简单的例子。

        Map<Integer,List<Integer>> map = new HashMap<>();
        System.out.println(map);
        map.computeIfAbsent(10, k-> new ArrayList<>()).add(20);
        System.out.println(map);
        map.computeIfAbsent(10, k-> new ArrayList<>()).add(30);
        System.out.println(map);
        

        computeIfAbsent 从 Java 1.8 开始可用

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-21
          • 2017-04-15
          • 2019-02-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多