本文目录导读:

我来为您设计一个Java赛季累计数据对比的案例,包含完整的代码实现和设计思路。
数据模型设计
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
// 球员赛季数据实体
class PlayerSeasonStats {
private String playerId;
private String playerName;
private String season; // "2023-2024"
private int gamesPlayed;
private int points;
private int rebounds;
private int assists;
private int steals;
private int blocks;
private double minutesPerGame;
private double fieldGoalPercentage;
// 构造函数、getter/setter省略,使用Lombok或手动生成
// 计算场均得分
public double getPointsPerGame() {
return gamesPlayed == 0 ? 0 : (double) points / gamesPlayed;
}
@Override
public String toString() {
return String.format("%s %s: %.1f分 %.1f板 %.1f助 %.1f断 %.1f帽 (%.1f分钟/场)",
playerName, season, getPointsPerGame(),
(double) rebounds / gamesPlayed,
(double) assists / gamesPlayed,
(double) steals / gamesPlayed,
(double) blocks / gamesPlayed,
minutesPerGame);
}
}
数据对比分析类
class SeasonStatsComparator {
// 对比两个赛季数据
public static Map<String, Object> compareSeasons(
List<PlayerSeasonStats> season1Data,
List<PlayerSeasonStats> season2Data) {
Map<String, Object> result = new HashMap<>();
// 1. 整体数据对比
Map<String, Double> season1Avg = calculateTeamAverages(season1Data);
Map<String, Double> season2Avg = calculateTeamAverages(season2Data);
// 2. 球员个人对比
List<PlayerComparison> playerComparisons = comparePlayers(season1Data, season2Data);
// 3. 进步最快球员
List<PlayerComparison> mostImproved = findMostImproved(playerComparisons);
// 4. 数据统计摘要
Map<String, Object> summary = createSummary(season1Data, season2Data);
result.put("season1Avg", season1Avg);
result.put("season2Avg", season2Avg);
result.put("playerComparisons", playerComparisons);
result.put("mostImproved", mostImproved);
result.put("summary", summary);
return result;
}
// 计算球队平均数据
private static Map<String, Double> calculateTeamAverages(List<PlayerSeasonStats> stats) {
Map<String, Double> averages = new HashMap<>();
if (stats.isEmpty()) return averages;
double totalPoints = stats.stream().mapToDouble(PlayerSeasonStats::getPointsPerGame).sum();
double totalRebounds = stats.stream()
.mapToDouble(s -> (double) s.getRebounds() / s.getGamesPlayed()).sum();
double totalAssists = stats.stream()
.mapToDouble(s -> (double) s.getAssists() / s.getGamesPlayed()).sum();
averages.put("points", round(totalPoints / stats.size()));
averages.put("rebounds", round(totalRebounds / stats.size()));
averages.put("assists", round(totalAssists / stats.size()));
averages.put("gamesPlayed", round(stats.stream().mapToInt(PlayerSeasonStats::getGamesPlayed).average().orElse(0)));
return averages;
}
// 球员对比
private static List<PlayerComparison> comparePlayers(
List<PlayerSeasonStats> season1,
List<PlayerSeasonStats> season2) {
Map<String, PlayerSeasonStats> season2Map = season2.stream()
.collect(Collectors.toMap(PlayerSeasonStats::getPlayerId, p -> p));
return season1.stream()
.filter(s1 -> season2Map.containsKey(s1.getPlayerId()))
.map(s1 -> {
PlayerSeasonStats s2 = season2Map.get(s1.getPlayerId());
return createPlayerComparison(s1, s2);
})
.sorted(Comparator.comparingDouble(PlayerComparison::getPointsDiff).reversed())
.collect(Collectors.toList());
}
// 创建球员对比对象
private static PlayerComparison createPlayerComparison(
PlayerSeasonStats s1, PlayerSeasonStats s2) {
PlayerComparison pc = new PlayerComparison();
pc.setPlayerId(s1.getPlayerId());
pc.setPlayerName(s1.getPlayerName());
pc.setSeason1Data(s1);
pc.setSeason2Data(s2);
// 计算差异
pc.setPointsDiff(s2.getPointsPerGame() - s1.getPointsPerGame());
pc.setReboundsDiff((double) s2.getRebounds()/s2.getGamesPlayed() -
(double) s1.getRebounds()/s1.getGamesPlayed());
pc.setAssistsDiff((double) s2.getAssists()/s2.getGamesPlayed() -
(double) s1.getAssists()/s1.getGamesPlayed());
return pc;
}
// 找出进步最快球员
private static List<PlayerComparison> findMostImproved(List<PlayerComparison> comparisons) {
return comparisons.stream()
.sorted(Comparator.comparingDouble(PlayerComparison::getPointsDiff).reversed())
.limit(5)
.collect(Collectors.toList());
}
// 创建数据摘要
private static Map<String, Object> createSummary(
List<PlayerSeasonStats> season1,
List<PlayerSeasonStats> season2) {
Map<String, Object> summary = new HashMap<>();
// 总得分对比
int totalPoints1 = season1.stream().mapToInt(PlayerSeasonStats::getPoints).sum();
int totalPoints2 = season2.stream().mapToInt(PlayerSeasonStats::getPoints).sum();
summary.put("totalPoints1", totalPoints1);
summary.put("totalPoints2", totalPoints2);
summary.put("pointsChange", totalPoints2 - totalPoints1);
summary.put("pointsChangePercent",
totalPoints1 == 0 ? 0 : ((totalPoints2 - totalPoints1) / (double) totalPoints1 * 100));
return summary;
}
private static double round(double value) {
return Math.round(value * 100.0) / 100.0;
}
// 球员对比数据传输对象
static class PlayerComparison {
private String playerId;
private String playerName;
private PlayerSeasonStats season1Data;
private PlayerSeasonStats season2Data;
private double pointsDiff;
private double reboundsDiff;
private double assistsDiff;
// getters and setters 省略
@Override
public String toString() {
return String.format("%s: 从%.1f分提升到%.1f分 (+%.1f)",
playerName,
season1Data.getPointsPerGame(),
season2Data.getPointsPerGame(),
pointsDiff);
}
}
}
可视化报表生成器
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class SeasonReportGenerator {
// 生成文本报告
public static String generateTextReport(Map<String, Object> comparison) {
StringBuilder report = new StringBuilder();
report.append("========== 赛季数据对比报告 ==========\n\n");
// 球队平均数据
report.append("【球队平均数据】\n");
@SuppressWarnings("unchecked")
Map<String, Double> season1Avg = (Map<String, Double>) comparison.get("season1Avg");
@SuppressWarnings("unchecked")
Map<String, Double> season2Avg = (Map<String, Double>) comparison.get("season2Avg");
report.append(String.format("赛季1: 得分%.1f 篮板%.1f 助攻%.1f\n",
season1Avg.get("points"), season1Avg.get("rebounds"), season1Avg.get("assists")));
report.append(String.format("赛季2: 得分%.1f 篮板%.1f 助攻%.1f\n",
season2Avg.get("points"), season2Avg.get("rebounds"), season2Avg.get("assists")));
// 个人对比
report.append("\n【球员对比】\n");
@SuppressWarnings("unchecked")
List<SeasonStatsComparator.PlayerComparison> comparisons =
(List<SeasonStatsComparator.PlayerComparison>) comparison.get("playerComparisons");
comparisons.stream()
.limit(10)
.forEach(pc -> report.append(pc.toString()).append("\n"));
// 进步最快球员
report.append("\n【进步最快球员 TOP5】\n");
@SuppressWarnings("unchecked")
List<SeasonStatsComparator.PlayerComparison> improved =
(List<SeasonStatsComparator.PlayerComparison>) comparison.get("mostImproved");
improved.forEach(pc -> report.append(pc.toString()).append("\n"));
// 数据摘要
report.append("\n【数据摘要】\n");
@SuppressWarnings("unchecked")
Map<String, Object> summary = (Map<String, Object>) comparison.get("summary");
report.append(String.format("总得分变化: %d (%.1f%%)\n",
summary.get("pointsChange"), summary.get("pointsChangePercent")));
return report.toString();
}
// 生成HTML报告
public static String generateHtmlReport(Map<String, Object> comparison) {
StringBuilder html = new StringBuilder();
html.append("<!DOCTYPE html><html><head><title>赛季数据对比</title>");
html.append("<style>body{font-family:sans-serif;margin:20px}table{border-collapse:collapse}")
.append("th,td{border:1px solid #ddd;padding:8px;text-align:center}")
.append("th{background-color:#f2f2f2}</style></head><body>");
html.append("<h1>赛季数据对比报告</h1>");
// 球队平均数据表格
html.append("<h2>球队平均数据</h2><table><tr><th>指标</th><th>赛季1</th><th>赛季2</th><th>变化</th></tr>");
@SuppressWarnings("unchecked")
Map<String, Double> s1Avg = (Map<String, Double>) comparison.get("season1Avg");
@SuppressWarnings("unchecked")
Map<String, Double> s2Avg = (Map<String, Double>) comparison.get("season2Avg");
String[] metrics = {"points", "rebounds", "assists"};
String[] metricNames = {"得分", "篮板", "助攻"};
for (int i = 0; i < metrics.length; i++) {
double diff = s2Avg.get(metrics[i]) - s1Avg.get(metrics[i]);
String color = diff >= 0 ? "green" : "red";
html.append(String.format(
"<tr><td>%s</td><td>%.1f</td><td>%.1f</td><td style='color:%s'>%+.1f</td></tr>",
metricNames[i], s1Avg.get(metrics[i]), s2Avg.get(metrics[i]), color, diff));
}
html.append("</table>");
// 球员对比表格
html.append("<h2>主要球员对比</h2><table><tr><th>球员</th><th>赛季1得分</th><th>赛季2得分</th><th>变化</th></tr>");
@SuppressWarnings("unchecked")
List<SeasonStatsComparator.PlayerComparison> comparisons =
(List<SeasonStatsComparator.PlayerComparison>) comparison.get("playerComparisons");
comparisons.stream().limit(15).forEach(pc -> {
String color = pc.getPointsDiff() >= 0 ? "green" : "red";
html.append(String.format(
"<tr><td>%s</td><td>%.1f</td><td>%.1f</td><td style='color:%s'>%+.1f</td></tr>",
pc.getPlayerName(),
pc.getSeason1Data().getPointsPerGame(),
pc.getSeason2Data().getPointsPerGame(),
color, pc.getPointsDiff()));
});
html.append("</table>");
html.append("</body></html>");
return html.toString();
}
}
主程序示例
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class SeasonComparisonDemo {
public static void main(String[] args) {
// 模拟数据生成
List<PlayerSeasonStats> season2022 = generateMockData("2022-2023");
List<PlayerSeasonStats> season2023 = generateMockData("2023-2024");
// 数据对比
Map<String, Object> comparison = SeasonStatsComparator.compareSeasons(season2022, season2023);
// 输出报告
System.out.println(SeasonReportGenerator.generateTextReport(comparison));
// 生成HTML报告
String htmlReport = SeasonReportGenerator.generateHtmlReport(comparison);
System.out.println("HTML报告已生成,长度:" + htmlReport.length() + " 字符");
}
// 模拟数据生成器
private static List<PlayerSeasonStats> generateMockData(String season) {
List<PlayerSeasonStats> players = new ArrayList<>();
// 模拟球员数据 - 实际情况从数据库或文件读取
String[][] playerNames = {
{"001", "张三"}, {"002", "李四"}, {"003", "王五"},
{"004", "赵六"}, {"005", "孙七"}, {"006", "周八"},
{"007", "吴九"}, {"008", "郑十"}, {"009", "王明"},
{"010", "李华"}, {"011", "张伟"}, {"012", "刘洋"}
};
Random random = new Random();
for (String[] player : playerNames) {
PlayerSeasonStats stats = new PlayerSeasonStats();
stats.setPlayerId(player[0]);
stats.setPlayerName(player[1]);
stats.setSeason(season);
stats.setGamesPlayed(70 + random.nextInt(10));
stats.setPoints(500 + random.nextInt(800));
stats.setRebounds(200 + random.nextInt(300));
stats.setAssists(150 + random.nextInt(250));
stats.setSteals(30 + random.nextInt(50));
stats.setBlocks(20 + random.nextInt(40));
stats.setMinutesPerGame(25 + random.nextDouble() * 10);
stats.setFieldGoalPercentage(40 + random.nextDouble() * 15);
players.add(stats);
}
return players;
}
}
高级功能扩展
// 趋势分析
class SeasonTrendAnalyzer {
// 分析多赛季趋势
public static Map<String, PlayerTrend> analyzeTrend(
Map<String, List<PlayerSeasonStats>> seasonData) {
Map<String, PlayerTrend> trends = new HashMap<>();
seasonData.forEach((playerId, seasons) -> {
PlayerTrend trend = new PlayerTrend();
trend.setPlayerId(playerId);
trend.setPlayerName(seasons.get(0).getPlayerName());
// 计算得分趋势
List<Double> pointsBySeason = seasons.stream()
.map(PlayerSeasonStats::getPointsPerGame)
.collect(Collectors.toList());
trend.setPointsTrend(pointsBySeason);
// 线性回归预测
trend.setPredictedPoints(linearRegressionPredict(pointsBySeason));
trends.put(playerId, trend);
});
return trends;
}
// 线性回归预测
private static double linearRegressionPredict(List<Double> data) {
if (data.size() < 2) return data.get(0);
int n = data.size();
double sumX = 0, sumY = 0, sumXY = 0, sumXX = 0;
for (int i = 0; i < n; i++) {
sumX += i;
sumY += data.get(i);
sumXY += i * data.get(i);
sumXX += i * i;
}
double slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
double intercept = (sumY - slope * sumX) / n;
// 预测下一赛季
return slope * n + intercept;
}
static class PlayerTrend {
private String playerId;
private String playerName;
private List<Double> pointsTrend;
private double predictedPoints;
// getters and setters 省略
}
}
使用注意事项
-
数据源处理:实际项目中,数据通常来自数据库或API,需要建立相应的数据访问层。
-
性能优化:对于大量数据,考虑使用并行流或数据库聚合查询。
-
缓存机制:频繁查询的数据可以使用缓存(如Redis)提高性能。
-
数据验证:确保数据的完整性和准确性,处理缺失值。
-
报表定制:根据实际需求,可以扩展图表(使用JFreeChart等库)和导出功能。
这个案例涵盖了赛季数据对比的核心功能,您可以根据实际需求进行扩展和优化,需要我详细解释某个部分吗?