计算地图的值
Counting the values of a map
以下地图包含以下形式的数据:
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(";"));
}
}
现在,我想实现一个方法来计算每个键的条目数,或者换句话说,每个日期在列表中出现的次数。它应 return 两个日期(即用户输入)之间的所有日期和每个键的值的数量。我从以下代码开始
/**
* 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()));
}
}
但我在使用过滤器和收集器方法时遇到了问题。我该如何完成?
使用 Collectors.groupingBy
按 Weather
的日期分组 class 和 Collectors.counting()
计算每组的大小。
Map<LocalDate, Long> counts = weatherData.subMap(dateFrom ,dateTo)
.values()
.stream()
.flatMap(List::stream)
.collect(Collectors.groupingBy(p -> p.getDate(), Collectors.counting()));
您实际上需要的是将日期作为地图的关键元素进行分组。在值中,您想要每个键出现的次数。
为此,您必须在收集地图时使用 Collectors.groupingBy
。对于价值,它只是 Collectors.counting()
。请查看下面的代码片段以获取更多详细信息:
Map<LocalDate, Long> countMap = weatherData
.subMap(dateFrom ,dateTo)
.values()
.stream()
.flatMap(List::stream)
.collect(Collectors.groupingBy(p -> p.getDate(), Collectors.counting()));
由于您正在使用流来简化代码,因此您可能还想执行以下操作。
而不是做
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
作为值。无论如何,return 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
以来可用
以下地图包含以下形式的数据:
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(";"));
}
}
现在,我想实现一个方法来计算每个键的条目数,或者换句话说,每个日期在列表中出现的次数。它应 return 两个日期(即用户输入)之间的所有日期和每个键的值的数量。我从以下代码开始
/**
* 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()));
}
}
但我在使用过滤器和收集器方法时遇到了问题。我该如何完成?
使用 Collectors.groupingBy
按 Weather
的日期分组 class 和 Collectors.counting()
计算每组的大小。
Map<LocalDate, Long> counts = weatherData.subMap(dateFrom ,dateTo)
.values()
.stream()
.flatMap(List::stream)
.collect(Collectors.groupingBy(p -> p.getDate(), Collectors.counting()));
您实际上需要的是将日期作为地图的关键元素进行分组。在值中,您想要每个键出现的次数。
为此,您必须在收集地图时使用 Collectors.groupingBy
。对于价值,它只是 Collectors.counting()
。请查看下面的代码片段以获取更多详细信息:
Map<LocalDate, Long> countMap = weatherData
.subMap(dateFrom ,dateTo)
.values()
.stream()
.flatMap(List::stream)
.collect(Collectors.groupingBy(p -> p.getDate(), Collectors.counting()));
由于您正在使用流来简化代码,因此您可能还想执行以下操作。
而不是做
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
作为值。无论如何,return 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
以来可用