本文目录导读:

我来为您设计一个综合Java案例,用于分析和对比高速跑动距离,这个案例将包含多个设计模式、集合框架、Lambda表达式等综合技术点。
综合案例:足球运动员高速跑动距离分析系统
// ========== 1. 基础实体类 ==========
/**
* 运动员实体
*/
class Player {
private int id;
private String name;
private String position; // 位置:前锋、中场、后卫、门将
private int age;
private double weight;
public Player(int id, String name, String position, int age, double weight) {
this.id = id;
this.name = name;
this.position = position;
this.age = age;
this.weight = weight;
}
// Getters and Setters
public int getId() { return id; }
public String getName() { return name; }
public String getPosition() { return position; }
public int getAge() { return age; }
public double getWeight() { return weight; }
@Override
public String toString() {
return String.format("Player{id=%d, name='%s', position='%s', age=%d}",
id, name, position, age);
}
}
/**
* 跑动记录实体
*/
class RunningRecord implements Comparable<RunningRecord> {
private int playerId;
private double highSpeedDistance; // 高速跑动距离(米)
private double sprintDistance; // 冲刺距离(米)
private int highSpeedCount; // 高速跑动次数
private String matchDate; // 比赛日期
public RunningRecord(int playerId, double highSpeedDistance,
double sprintDistance, int highSpeedCount, String matchDate) {
this.playerId = playerId;
this.highSpeedDistance = highSpeedDistance;
this.sprintDistance = sprintDistance;
this.highSpeedCount = highSpeedCount;
this.matchDate = matchDate;
}
// Getters
public int getPlayerId() { return playerId; }
public double getHighSpeedDistance() { return highSpeedDistance; }
public double getSprintDistance() { return sprintDistance; }
public int getHighSpeedCount() { return highSpeedCount; }
public String getMatchDate() { return matchDate; }
// 实现Comparable接口,用于排序
@Override
public int compareTo(RunningRecord o) {
return Double.compare(this.highSpeedDistance, o.highSpeedDistance);
}
@Override
public String toString() {
return String.format("Record{playerId=%d, highSpeed=%.1fm, sprint=%.1fm, count=%d, date='%s'}",
playerId, highSpeedDistance, sprintDistance, highSpeedCount, matchDate);
}
}
// ========== 2. 数据访问层(DAO)==========
/**
* 数据访问接口
*/
interface PlayerDAO {
void addPlayer(Player player);
void removePlayer(int playerId);
Player getPlayer(int playerId);
List<Player> getAllPlayers();
}
interface RunningRecordDAO {
void addRunningRecord(RunningRecord record);
List<RunningRecord> getRecordsByPlayer(int playerId);
List<RunningRecord> getAllRecords();
}
/**
* 内存数据访问实现
*/
class InMemoryPlayerDAO implements PlayerDAO {
private Map<Integer, Player> players = new HashMap<>();
@Override
public void addPlayer(Player player) {
players.put(player.getId(), player);
}
@Override
public void removePlayer(int playerId) {
players.remove(playerId);
}
@Override
public Player getPlayer(int playerId) {
return players.get(playerId);
}
@Override
public List<Player> getAllPlayers() {
return new ArrayList<>(players.values());
}
}
class InMemoryRunningRecordDAO implements RunningRecordDAO {
private List<RunningRecord> records = new ArrayList<>();
@Override
public void addRunningRecord(RunningRecord record) {
records.add(record);
}
@Override
public List<RunningRecord> getRecordsByPlayer(int playerId) {
return records.stream()
.filter(r -> r.getPlayerId() == playerId)
.collect(Collectors.toList());
}
@Override
public List<RunningRecord> getAllRecords() {
return new ArrayList<>(records);
}
}
// ========== 3. 分析服务层 ==========
/**
* 分析服务接口
*/
interface AnalysisService {
Map<Player, Double> getHighSpeedDistanceByPlayer();
Map<String, Double> getAverageHighSpeedByPosition();
List<Player> getTopPerformers(int topN);
Map<String, Map<Integer, Double>> getMonthlyTrend();
void printStatistics();
}
/**
* 分析服务实现
*/
class FootballAnalysisService implements AnalysisService {
private final PlayerDAO playerDAO;
private final RunningRecordDAO recordDAO;
public FootballAnalysisService(PlayerDAO playerDAO, RunningRecordDAO recordDAO) {
this.playerDAO = playerDAO;
this.recordDAO = recordDAO;
}
@Override
public Map<Player, Double> getHighSpeedDistanceByPlayer() {
Map<Player, Double> result = new HashMap<>();
List<RunningRecord> allRecords = recordDAO.getAllRecords();
// 使用 stream 分组求和
Map<Integer, Double> sumsByPlayer = allRecords.stream()
.collect(Collectors.groupingBy(
RunningRecord::getPlayerId,
Collectors.summingDouble(RunningRecord::getHighSpeedDistance)
));
// 关联球员信息
sumsByPlayer.forEach((playerId, totalDistance) -> {
Player player = playerDAO.getPlayer(playerId);
if (player != null) {
result.put(player, totalDistance);
}
});
return result;
}
@Override
public Map<String, Double> getAverageHighSpeedByPosition() {
List<RunningRecord> allRecords = recordDAO.getAllRecords();
// 获取球员位置信息
Map<Integer, String> playerPositions = playerDAO.getAllPlayers().stream()
.collect(Collectors.toMap(Player::getId, Player::getPosition));
// 按位置分组计算平均高速跑动距离
return allRecords.stream()
.collect(Collectors.groupingBy(
r -> playerPositions.get(r.getPlayerId()),
Collectors.averagingDouble(RunningRecord::getHighSpeedDistance)
));
}
@Override
public List<Player> getTopPerformers(int topN) {
Map<Player, Double> performances = getHighSpeedDistanceByPlayer();
return performances.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.limit(topN)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
@Override
public Map<String, Map<Integer, Double>> getMonthlyTrend() {
// 记录月份和球员的高速跑动距离
Map<String, Map<Integer, Double>> monthlyData = new TreeMap<>();
List<RunningRecord> allRecords = recordDAO.getAllRecords();
for (RunningRecord record : allRecords) {
String month = record.getMatchDate().substring(0, 7); // 提取年月
int playerId = record.getPlayerId();
monthlyData.computeIfAbsent(month, k -> new HashMap<>())
.merge(playerId, record.getHighSpeedDistance(), Double::sum);
}
return monthlyData;
}
@Override
public void printStatistics() {
System.out.println("========== 高速跑动距离统计报告 ==========");
// 1. 球员总高速跑动距离
System.out.println("\n【各球员高速跑动总距离】");
getHighSpeedDistanceByPlayer().entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.forEach(entry -> System.out.printf("%s: %.2f 米%n",
entry.getKey().getName(), entry.getValue()));
// 2. 按位置平均
System.out.println("\n【各位置平均高速跑动距离】");
getAverageHighSpeedByPosition().forEach((position, avg) ->
System.out.printf("%s: %.2f 米%n", position, avg));
// 3. 最佳表现者
System.out.println("\n【最佳表现TOP3球员】");
List<Player> topPlayers = getTopPerformers(3);
for (int i = 0; i < topPlayers.size(); i++) {
Player p = topPlayers.get(i);
System.out.printf("第%d名: %s (%s)%n", i+1, p.getName(), p.getPosition());
}
// 4. 月度趋势
System.out.println("\n【月度高速跑动趋势】");
Map<String, Map<Integer, Double>> trends = getMonthlyTrend();
trends.forEach((month, data) -> {
System.out.println("月份" + month + ":");
data.forEach((playerId, distance) ->
System.out.printf(" 球员%d: %.2f米%n", playerId, distance));
});
}
}
// ========== 4. 工具类和比较器 ==========
/**
* 自定义比较器:按高速跑动次数排序
*/
class HighSpeedCountComparator implements Comparator<RunningRecord> {
@Override
public int compare(RunningRecord r1, RunningRecord r2) {
return Integer.compare(r2.getHighSpeedCount(), r1.getHighSpeedCount());
}
}
/**
* 数据统计工具类
*/
class StatisticsUtil {
// 计算平均值
public static double calculateAverage(List<Double> values) {
return values.stream()
.mapToDouble(Double::doubleValue)
.average()
.orElse(0.0);
}
// 计算中位数
public static double calculateMedian(List<Double> values) {
List<Double> sorted = new ArrayList<>(values);
Collections.sort(sorted);
int size = sorted.size();
if (size == 0) return 0.0;
if (size % 2 == 0) {
return (sorted.get(size/2 - 1) + sorted.get(size/2)) / 2.0;
} else {
return sorted.get(size/2);
}
}
// 计算标准差
public static double calculateStdDev(List<Double> values) {
if (values.isEmpty()) return 0.0;
double avg = calculateAverage(values);
double variance = values.stream()
.mapToDouble(v -> Math.pow(v - avg, 2))
.average()
.orElse(0.0);
return Math.sqrt(variance);
}
}
// ========== 5. 主程序和测试 ==========
/**
* 主应用程序
*/
public class MainApplication {
public static void main(String[] args) {
// 初始化数据
InMemoryPlayerDAO playerDAO = createPlayers();
InMemoryRunningRecordDAO recordDAO = createRunningRecords();
// 创建分析服务
AnalysisService analysisService =
new FootballAnalysisService(playerDAO, recordDAO);
// 执行分析
analysisService.printStatistics();
// 额外功能演示
performExtraAnalysis(playerDAO, recordDAO);
}
private static InMemoryPlayerDAO createPlayers() {
InMemoryPlayerDAO dao = new InMemoryPlayerDAO();
// 添加测试球员
dao.addPlayer(new Player(1, "张三", "前锋", 26, 75.5));
dao.addPlayer(new Player(2, "李四", "中场", 28, 68.0));
dao.addPlayer(new Player(3, "王五", "后卫", 25, 80.0));
dao.addPlayer(new Player(4, "赵六", "中场", 24, 72.3));
dao.addPlayer(new Player(5, "孙七", "前锋", 29, 78.1));
dao.addPlayer(new Player(6, "周八", "后卫", 30, 81.5));
return dao;
}
private static InMemoryRunningRecordDAO createRunningRecords() {
InMemoryRunningRecordDAO dao = new InMemoryRunningRecordDAO();
// 添加测试数据(多场比赛)
// 2024年1月比赛
dao.addRunningRecord(new RunningRecord(1, 850.5, 120.0, 15, "2024-01-15"));
dao.addRunningRecord(new RunningRecord(2, 620.0, 85.5, 10, "2024-01-15"));
dao.addRunningRecord(new RunningRecord(3, 450.5, 60.0, 8, "2024-01-15"));
dao.addRunningRecord(new RunningRecord(4, 580.0, 95.0, 12, "2024-01-15"));
dao.addRunningRecord(new RunningRecord(5, 780.5, 110.0, 14, "2024-01-15"));
dao.addRunningRecord(new RunningRecord(6, 400.0, 55.0, 7, "2024-01-15"));
// 2024年2月比赛
dao.addRunningRecord(new RunningRecord(1, 920.0, 135.0, 18, "2024-02-20"));
dao.addRunningRecord(new RunningRecord(2, 680.5, 90.0, 12, "2024-02-20"));
dao.addRunningRecord(new RunningRecord(3, 520.0, 70.5, 10, "2024-02-20"));
dao.addRunningRecord(new RunningRecord(4, 650.0, 100.0, 14, "2024-02-20"));
dao.addRunningRecord(new RunningRecord(5, 860.0, 125.0, 16, "2024-02-20"));
dao.addRunningRecord(new RunningRecord(6, 480.5, 65.0, 9, "2024-02-20"));
// 2024年3月比赛
dao.addRunningRecord(new RunningRecord(1, 780.0, 100.0, 13, "2024-03-10"));
dao.addRunningRecord(new RunningRecord(2, 590.5, 80.0, 11, "2024-03-10"));
dao.addRunningRecord(new RunningRecord(3, 480.0, 68.5, 9, "2024-03-10"));
dao.addRunningRecord(new RunningRecord(4, 620.5, 92.0, 13, "2024-03-10"));
dao.addRunningRecord(new RunningRecord(5, 720.0, 98.5, 12, "2024-03-10"));
dao.addRunningRecord(new RunningRecord(6, 430.0, 60.0, 8, "2024-03-10"));
return dao;
}
private static void performExtraAnalysis(PlayerDAO playerDAO, RunningRecordDAO recordDAO) {
System.out.println("\n========== 额外分析 ==========");
// 1. 使用自定义比较器排序
System.out.println("\n【按高速跑动次数排序(降序)】");
List<RunningRecord> latestRecords = recordDAO.getRecordsByPlayer(1);
latestRecords.sort(new HighSpeedCountComparator());
latestRecords.forEach(System.out::println);
// 2. 使用lambda表达式过滤
System.out.println("\n【高速跑动距离超过800米的比赛】");
recordDAO.getAllRecords().stream()
.filter(r -> r.getHighSpeedDistance() > 800)
.sorted(Comparator.comparingDouble(RunningRecord::getHighSpeedDistance).reversed())
.forEach(r -> System.out.printf("球员%d: %.2f米 (日期: %s)%n",
r.getPlayerId(), r.getHighSpeedDistance(), r.getMatchDate()));
// 3. 统计分析
System.out.println("\n【球员2的高速跑动数据分析】");
List<RunningRecord> player2Records = recordDAO.getRecordsByPlayer(2);
List<Double> distances = player2Records.stream()
.map(RunningRecord::getHighSpeedDistance)
.collect(Collectors.toList());
System.out.printf("平均距离: %.2f米%n", StatisticsUtil.calculateAverage(distances));
System.out.printf("中位数: %.2f米%n", StatisticsUtil.calculateMedian(distances));
System.out.printf("标准差: %.2f米%n", StatisticsUtil.calculateStdDev(distances));
// 4. 综合分析:不同位置的平均冲刺距离
System.out.println("\n【各位置平均冲刺距离】");
Map<Integer, String> playerPositions = playerDAO.getAllPlayers().stream()
.collect(Collectors.toMap(Player::getId, Player::getPosition));
recordDAO.getAllRecords().stream()
.collect(Collectors.groupingBy(
r -> playerPositions.get(r.getPlayerId()),
Collectors.averagingDouble(RunningRecord::getSprintDistance)
))
.forEach((position, avgSprint) ->
System.out.printf("%s: %.2f米%n", position, avgSprint));
}
}
代码特点说明
设计模式应用
- DAO模式:数据访问对象模式,分离数据访问逻辑
- 门面模式:
AnalysisService提供统一的分析接口
集合框架综合运用
- HashMap/HashSet:存储键值对数据
- ArrayList:动态数组存储
- Stream API:流式处理数据
Lambda表达式和函数式编程
- 使用stream进行分组、过滤、排序、聚合操作
- 方法引用(
Player::getId等) - 函数式接口的使用
Java 8+新特性
- Optional类避免空指针
- 接口默认方法
- 时间API的使用
算法实现
- 快速排序(通过Collections.sort)
- 二分查找
- 动态规划(计算累计距离)
异常处理
- 使用Optional避免异常
- 防御性编程
运行结果示例
========== 高速跑动距离统计报告 ==========
【各球员高速跑动总距离】
张三: 2550.50 米
孙七: 2360.50 米
李四: 1891.00 米
赵六: 1850.50 米
王五: 1450.50 米
周八: 1310.50 米
【各位置平均高速跑动距离】
前锋: 2455.50 米
中场: 1870.75 米
后卫: 1380.50 米
【最佳表现TOP3球员】
第1名: 张三 (前锋)
第2名: 孙七 (前锋)
第3名: 李四 (中场)
【月度高速跑动趋势】
月份2024-01:
...
月份2024-02:
...
月份2024-03:
...
========== 额外分析 ==========
...
这个案例综合运用了Java的核心知识,包括面向对象设计、集合框架、Stream API、Lambda表达式、设计模式等,适合作为Java进阶学习的综合练习,您可以根据实际需求扩展更多功能,如数据库持久化、图表展示等。