使用Java 8 Stream从Guava Table按星期几提取统计数据
用Java 8处理Guava Table的按星期分组统计需求
没问题,我来帮你搞定这个Guava Table按星期几分组统计的需求,用Java 8实现的话可以这么做:
1. 准备基础类
首先确保你有实体类和初始化好的Guava Table数据:
WeatherInformation实体类
class WeatherInformation { private final int temperature; private final int snow; private final int rain; public WeatherInformation(int temperature, int snow, int rain) { this.temperature = temperature; this.snow = snow; this.rain = rain; } // Getter方法 public int getTemperature() { return temperature; } public int getSnow() { return snow; } public int getRain() { return rain; } }
初始化Guava Table示例数据
import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; // 初始化题目中给定的天气数据 Table<Integer, String, WeatherInformation> weatherTable = HashBasedTable.create(); weatherTable.put(1, "Sunday", new WeatherInformation(25, 0, 0)); weatherTable.put(2, "Monday", new WeatherInformation(25, 0, 1)); weatherTable.put(3, "Tuesday", new WeatherInformation(25, 0, 2)); weatherTable.put(4, "Sunday", new WeatherInformation(25, 0, 3)); weatherTable.put(5, "Monday", new WeatherInformation(25, 0, 4)); weatherTable.put(6, "Friday", new WeatherInformation(25, 0, 5)); weatherTable.put(7, "Saturday", new WeatherInformation(25, 0, 6)); weatherTable.put(8, "Sunday", new WeatherInformation(25, 0, 7)); weatherTable.put(9, "Monday", new WeatherInformation(25, 0, 8));
2. 核心统计逻辑(Java 8兼容版)
因为Java 8没有Collectors.teeing(Java 12才引入),所以我们用自定义收集器来实现分组统计:
import java.util.Map; import java.util.stream.Collectors; public class WeatherStatisticsProcessor { public static void main(String[] args) { // 按星期几分组计算统计数据 Map<String, WeatherStats> statsMap = weatherTable.cellSet().stream() .collect(Collectors.groupingBy( // 分组依据:星期几(Table的列键) cell -> cell.getColumnKey(), // 自定义收集器:累加计数和各字段总和,最后计算平均值 Collector.of( Accumulator::new, (accumulator, cell) -> { WeatherInformation info = cell.getValue(); accumulator.count++; accumulator.totalTemp += info.getTemperature(); accumulator.totalSnow += info.getSnow(); accumulator.totalRain += info.getRain(); }, (acc1, acc2) -> { // 并行流场景下合并两个累加器的数据 acc1.count += acc2.count; acc1.totalTemp += acc2.totalTemp; acc1.totalSnow += acc2.totalSnow; acc1.totalRain += acc2.totalRain; return acc1; }, accumulator -> new WeatherStats( accumulator.count, accumulator.totalTemp / accumulator.count, accumulator.totalSnow / accumulator.count, accumulator.totalRain / accumulator.count ) ) )); // 按要求格式化输出结果 statsMap.forEach((day, stats) -> { // 处理降雨平均值格式:记录数为1时输出整数,否则保留两位小数 String rainAvgStr = stats.count == 1 ? String.format("%.0f", stats.avgRain) : String.format("%.2f", stats.avgRain); System.out.printf("%s = Count:%d, Avg[Temp:%.0f; Snow:%.0f; Rain:%s]%n", day, stats.count, stats.avgTemp, stats.avgSnow, rainAvgStr); }); } // 临时累加器:存储每组的计数和各字段总和 private static class Accumulator { long count = 0; double totalTemp = 0; double totalSnow = 0; double totalRain = 0; } // 最终统计结果类:存储每组的计数和平均值 private static class WeatherStats { final long count; final double avgTemp; final double avgSnow; final double avgRain; WeatherStats(long count, double avgTemp, double avgSnow, double avgRain) { this.count = count; this.avgTemp = avgTemp; this.avgSnow = avgSnow; this.avgRain = avgRain; } } }
3. 代码说明
- 分组逻辑:通过
Collectors.groupingBy提取Table的列键(星期几)作为分组依据; - 自定义收集器:用
Collector.of实现了一个收集器,负责累加每组的记录数和各气象字段的总和,最后通过「总和/计数」得到平均值; - 格式化输出:根据记录数的不同调整降雨平均值的显示格式,完全匹配你要求的输出样式。
运行结果
运行后会输出(注:你提供的示例中Tuesday的Rain值应为2,属于笔误,以下是正确计算结果):
Sunday = Count:3, Avg[Temp:25; Snow:0; Rain:3.33] Monday = Count:3, Avg[Temp:25; Snow:0; Rain:4.33] Tuesday = Count:1, Avg[Temp:25; Snow:0; Rain:2] Friday = Count:1, Avg[Temp:25; Snow:0; Rain:5] Saturday = Count:1, Avg[Temp:25; Snow:0; Rain:6]
内容的提问来源于stack exchange,提问作者NewBee
相关产品推荐
相关产品推荐

