我有一个类似于这样的温度记录
dt |AverageTemperature |AverageTemperatureUncertainty|City |Country |Latitude|Longitude
----------+-------------------+-----------------------------+-------+--------+--------+---------
1963-01-01|-5.417000000000002 |0.5 |Karachi|Pakistan|57.05N |10.33E
1963-02-01|-4.7650000000000015|0.328 |Karachi|Pakistan|57.05N |10.33E
1964-01-01|-5.417000000000002 |0.5 |Karachi|Pakistan|57.05N |10.33E
1964-02-01|-4.7650000000000015|0.328 |Karachi|Pakistan|57.05N |10.33E
1965-01-01|11.417000000000002 |0.5 |Karachi|Pakistan|57.05N |10.33E
1965-02-01|12.7650000000000015|0.328 |Karachi|Pakistan|57.05N |10.33E
我需要将其解析为POJO,并根据以下问题陈述计算平均增量:
使用Streams API计算每个国家的平均年温度增量。要计算增量,将1901年的平均温度减去1900年的平均温度,以获得特定城市从1900年到1901年的增量。所有这些增量的平均值是城市的平均年温度增量。一个国家所有城市的平均值是该国家的平均值。
我的Temperature POJO如下,具有getter和setter方法。
public class Temperature {
private java.util.Date date;
private double averageTemperature;
private double averageTemperatureUncertainty;
private String city;
private String country;
private String latitude;
private String longitude;
}
我已经维护了一个温度列表,因为这个问题需要使用流来实现。
为了计算delta,我正在尝试使用以下流,但我仍然无法计算出实际的delta,因为我必须计算平均国家delta,所以我对国家、城市和日期进行了分组。
Map<String, Map<String, Map<Integer, Double>>> countriesMap = this.getTemperatures().stream()
.sorted(Comparator.comparing(Temperature::getDate))
.collect(Collectors.groupingBy(Temperature::getCountry,
Collectors.groupingBy(Temperature::getCity,
Collectors.groupingBy
(t -> {
Calendar calendar = Calendar.getInstance();
calendar.setTime(t.getDate());
return calendar.get(Calendar.YEAR);
},
Collectors.averagingDouble(Temperature::getAverageTemperature)))));
为了计算delta值,我们需要计算
Map<Integer, Double>
的差异。为了计算差异,我想出了以下代码,但无法与上面的代码连接起来。
Stream.of(10d, 20d, 10d) //this is sample data that I that I get in `Map<Integer, Double>` of countriesMap
.map(new Function<Double, Optional<Double>>() {
Optional<Double> previousValue = Optional.empty();
@Override
public Optional<Double> apply(Double current) {
Optional<Double> value = previousValue.map(previous -> current - previous);
previousValue = Optional.of(current);
return value;
}
})
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println);
如何使用流一次性计算 delta,或者如何在 countriesMap
上执行流操作以计算 delta 并实现所述问题陈述?
double avgAnnualTempDeltaPerCity = cityMap.values().stream().mapToDouble(this::averagePerCity).average();
来代替AtomicReference<Double> cityAvgTemp = new AtomicReference<>((double) 0); cityMap.forEach((city, yearMap) -> cityAvgTemp.set(cityAvgTemp.get() + averagePerCity(yearMap))); double avgAnnualTempDeltaPerCity = cityAvgTemp.get() / cityMap.size();
。 - Holgerdouble avgAnnualTempDeltaPerCity = cityAvgTemp.get() / cityMap.size();
这不是avgAnnualTempDeltaPerCountry吗? - user2578909AtomicReference<Double> countryValAvg = new AtomicReference<>(0.0); countriesMap.forEach((country, cityMap) -> { /* code not using country */ countryValAvg.set(countryValAvg.get() + avgAnnualTempDeltaPerCity); }) double result = countryValAvg.get() / countriesMap.size();
,你可以直接使用double result = countriesMap.values().stream().mapToDouble(cityMap -> /* expression used to initialize avgAnnualTempDeltaPerCity */).average();
。 - Holger