我有個問題。我正在嘗試創建一個函式,該函式回傳 .csv 檔案中給定屬性的最大值Set<Measurement>。這是我現在擁有的功能:
public Map<Integer,Double> annualMaximumTrend(Function<Measurement,Double> mapper) {
Map<Integer, Double> maximumValue = new LinkedHashMap<>();
int startYear = determineStartYear();
for (int year = startYear; year <= LocalDate.now().getYear(); year ) {
LocalDate startDate = LocalDate.of(year - 1, 12, 31);
LocalDate endDate = LocalDate.of(year 1, 1, 1);
Set<Measurement> stationAverages = new HashSet<>();
for (Station station : stations.values()) {
stationAverages.addAll(station
.getMeasurements()
.stream()
.filter(m -> m.getDate().isAfter(startDate) &&
m.getDate().isBefore(endDate) &&
!Double.isNaN(mapper.apply(m))
).collect(Collectors.toSet()));
}
OptionalDouble maximum = stationAverages.stream().mapToDouble(Measurement::getMaxTemperature).max();
if (maximum.isPresent())
maximumValue.put(year, maximum.getAsDouble());
}
return maximumValue;
}
但是我需要確定maximum不同的,因為Measurement::getMaxTemperature我需要使用mapper.apply()某處而不是,因為該映射器決定了我想要哪個屬性的最大值。我需要如何使用映射器?
uj5u.com熱心網友回復:
您可以使用 lambda:
stationAverages.stream().mapToDouble(m -> mapper.apply(m)).max();
uj5u.com熱心網友回復:
如果mapper是 aToDoubleFunction<Measurement>你可以直接將它傳遞給mapToDouble(). 因為它不是你需要在另一個函式/lambda 中呼叫它,例如mapToDouble(m -> mapper.apply(m)).
或者,使用map(mapper).max(Comparator.naturalOrder())獲取Optional<Double>.
但是,請注意,您已經有 2 個內部回圈,并且不需要其中之一:
- 一個回圈來構建集合
- 使用流的一個(隱藏)回圈
您可以一次性完成所有操作:
Optional<Double> max = stations.values().stream()
.flatMap(station -> station
.getMeasurements()
.stream()
.filter(m -> m.getDate().isAfter(startDate) &&
m.getDate().isBefore(endDate)
)
.map(mapper)
.filter(v -> !Double.isNaN(v))
)
.max(Comparator.naturalOrder());
實際上,您甚至可以一口氣完成所有事情:
//stream the stations
Map<Integer, Double> maximumValue = stations.values().stream()
//flat map the stations to the measurements once
.flatMap(st -> st.getMeasurements().stream())
//filter measurements outside the time range
.filter(m -> m.getDate().getYear() >= startYear && m.getDate().getYear() <= endYear )
//filter measurements without a value
.filter(m -> !Double.isNaN(mapper.apply(m)))
//group measurements by year
.collect(Collectors.groupingBy(m->m.getDate().getYear(),
//map the grouped measurements to the value
Collectors.mapping(mapper,
//collect the max value and map it to a default value if it isn't present
//due to the filter above the default value should never be present
Collectors.collectingAndThen(
Collectors.maxBy(Comparator.naturalOrder()),
opt -> opt.orElse(Double.MIN_VALUE))
)));
這應該會在更長的時間段和更多的站點上提高性能,因為您只在站點上迭代一次而不是多次。復雜度應O(s*m)改為O(y*s*m)(y = 年數,s = 站點數,m = 每個站點的測量數)。
為了進行比較,這里有一個非流式功能等效項(由于不必解壓而更簡單Optional):
Map<Integer, Double> maximumValue = new LinkedHashMap<>();
for( Station station : stations.values() ) {
for( Measurement measurement : station.getMeasurements() ) {
//1st filter
if( !(measurement.getDate().getYear() >= startYear && measurement.getDate().getYear() <= endYear )) {
continue;
}
//2nd filter
if( Double.isNaN(mapper.apply(measurement))) {
continue;
}
//put the value into the map or replace it if the other one is larger
maximumValue.merge(measurement.getDate().getYear(), mapper.apply(measurement), Math::max );
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/369649.html
