本文目录导读:

- 业务场景设定
- 第一部分:定义选手实体(
Player) - 第二部分:业务逻辑层(
PlayOffService) - 第三部分:主程序入口(
Main) - 运行结果示例(每次都会随机,但逻辑一致)
- 这个案例涵盖了哪些核心Java知识点?
- 额外思考(如果你想进一步优化)
这是一个非常经典的综合Java案例,考察的是面向对象设计(OOP)、集合框架、Lambda表达式/Stream流、比较器以及业务逻辑的综合运用。
为了让你更直观地理解,我设计了一个“选秀节目晋级系统”的模拟场景。
业务场景设定
某选秀节目有 10 名选手,评委进行打分(满分100分)。 晋级规则(业务逻辑):
- 去掉一个最高分,去掉一个最低分(为了公平)。
- 计算剩余分数的平均分作为最终得分。
- 按照最终得分从高到低排序。
- 前 40%(即前4名)的选手直接晋级。
- 第5名到第7名进入待定区(有复活机会)。
- 后3名被淘汰。
第一部分:定义选手实体(Player)
使用 class 封装选手信息,利用 构造器 初始化。
import java.util.ArrayList;
import java.util.List;
// 选手类(JavaBean规范)
public class Player {
private int id; // 编号
private String name; // 姓名
private List<Double> scores; // 评委打分集合
// 构造器
public Player(int id, String name) {
this.id = id;
this.name = name;
this.scores = new ArrayList<>(); // 初始化列表,防止空指针
}
// Getter 和 Setter(这里只列出关键逻辑需要用到的)
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public List<Double> getScores() { return scores; }
// 添加评委打分的方法
public void addScore(double score) {
this.scores.add(score);
}
// 计算最终得分:去掉最高分和最低分,取平均
public double getFinalScore() {
if (scores == null || scores.size() < 3) {
return 0.0; // 如果评委不够,分数无效
}
// 使用 Stream 流实现
double sum = scores.stream()
.sorted() // 升序排序
.skip(1) // 跳过第一个(最低分)
.limit(scores.size() - 2) // 限制数量:总数减去2(去掉的头尾)
.mapToDouble(Double::doubleValue) // 转换为基本类型
.sum(); // 求和
// 有效评委人数 = 总人数 - 2
int validCount = scores.size() - 2;
double avg = sum / validCount;
// 保留两位小数
return Math.round(avg * 100.0) / 100.0;
}
@Override
public String toString() {
return "选手{编号=" + id + ", 姓名='" + name + '\'' +
", 最终得分=" + getFinalScore() + '}';
}
}
第二部分:业务逻辑层(PlayOffService)
使用 Stream API 和 Comparator 进行复杂的数据处理与分析。
import java.util.*;
import java.util.stream.Collectors;
// 晋级逻辑服务类
public class PlayOffService {
// 主方法:进行排名和分组
public static Map<String, List<Player>> evaluate(List<Player> allPlayers) {
// 1. 按照最终得分降序排序(从高到低)
// 使用 Comparator.comparingDouble 进行比较
List<Player> sortedPlayers = allPlayers.stream()
.sorted(Comparator.comparingDouble(Player::getFinalScore).reversed())
.collect(Collectors.toList());
// 2. 分组
Map<String, List<Player>> result = new HashMap<>();
int total = sortedPlayers.size();
int promoteCount = (int) Math.ceil(total * 0.4); // 前40%直接晋级(向上取整)
// 直接晋级:取前 N 个
List<Player> promoted = sortedPlayers.stream()
.limit(promoteCount)
.collect(Collectors.toList());
// 待定区:接下来的3个(如果有)
List<Player> pending = sortedPlayers.stream()
.skip(promoteCount) // 跳过晋级的
.limit(3) // 只取3个
.collect(Collectors.toList());
// 淘汰区:剩下的
List<Player> eliminated = sortedPlayers.stream()
.skip(promoteCount + pending.size()) // 跳过晋级的和待定的
.collect(Collectors.toList());
result.put("PROMOTED", promoted);
result.put("PENDING", pending);
result.put("ELIMINATED", eliminated);
return result;
}
// 打印结果的方法
public static void printResult(Map<String, List<Player>> result) {
System.out.println("========== 🏆 最终晋级名单 ==========");
System.out.println("\n【✨ 直接晋级】(前40%)");
result.get("PROMOTED").forEach(p -> System.out.println(" " + p));
System.out.println("\n【🕒 待定区】(可能被复活)");
result.get("PENDING").forEach(p -> System.out.println(" " + p));
System.out.println("\n【💔 惨遭淘汰】");
result.get("ELIMINATED").forEach(p -> System.out.println(" " + p));
}
}
第三部分:主程序入口(Main)
负责初始化数据、模拟评委打分并调用业务方法。
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class Main {
public static void main(String[] args) {
// 1. 初始化10名选手
List<Player> players = new ArrayList<>();
String[] names = {"小明", "小红", "小刚", "丽丽", "阿强", "壮壮", "妮妮", "乐乐", "糖糖", "天天"};
for (int i = 0; i < names.length; i++) {
players.add(new Player(i + 1, names[i]));
}
// 2. 模拟评委打分(使用 Random 模拟真实数据)
Random random = new Random();
for (Player p : players) {
int judgeCount = 5; // 假设5个评委
for (int i = 0; i < judgeCount; i++) {
// 打分范围 70.0 - 100.0,保留一位小数
double score = 70 + (random.nextDouble() * 30);
p.addScore(Math.round(score * 10.0) / 10.0);
}
}
// 3. 展示每个选手的原始数据(加分输出,便于对比)
System.out.println("========== 原始评委打分数据 ==========");
players.forEach(p -> System.out.println(p.getName() + " -> " + p.getScores()));
// 4. 进行晋级评估
Map<String, List<Player>> result = PlayOffService.evaluate(players);
// 5. 打印最终结果
PlayOffService.printResult(result);
// 6. 附加逻辑:找出全场最高分和最低分(演示 Lambda 用法)
Player bestPlayer = result.get("PROMOTED").get(0); // 第一名就是最高分
Player worstPlayer = players.stream()
.min(Comparator.comparingDouble(Player::getFinalScore))
.orElse(null);
System.out.println("\n【🏅 全场最高分】:" + bestPlayer.getName() + " (" + bestPlayer.getFinalScore() + "分)");
if (worstPlayer != null) {
System.out.println("【📉 全场最低分】:" + worstPlayer.getName() + " (" + worstPlayer.getFinalScore() + "分)");
}
}
}
运行结果示例(每次都会随机,但逻辑一致)
========== 原始评委打分数据 ==========
小明 -> [90.5, 85.2, 78.9, 95.1, 88.3]
小红 -> [82.1, 91.4, 79.2, 88.7, 86.5]
... (略)
========== 🏆 最终晋级名单 ==========
【✨ 直接晋级】(前40%)
选手{编号=3, 姓名='小刚', 最终得分=91.24}
选手{编号=1, 姓名='小明', 最终得分=89.56}
选手{编号=7, 姓名='妮妮', 最终得分=87.33}
选手{编号=5, 姓名='阿强', 最终得分=86.99}
【🕒 待定区】(可能被复活)
选手{编号=2, 姓名='小红', 最终得分=84.21}
选手{编号=9, 姓名='糖糖', 最终得分=82.78}
选手{编号=4, 姓名='丽丽', 最终得分=81.55}
【💔 惨遭淘汰】
...
这个案例涵盖了哪些核心Java知识点?
| 技术点 | 实际应用场景 |
|---|---|
| 面向对象 (OOP) | Player 类封装数据与行为(addScore、getFinalScore)。 |
| 集合框架 | ArrayList 存储选手;HashMap 存储分组结果;List 作为方法返回值。 |
| Stream API | sorted() 排序;limit() 截断;skip() 跳过;collect() 收集到集合。 |
| Lambda表达式 | p -> System.out.println(p) 替代匿名内部类。 |
| 方法引用 | Player::getFinalScore 用来提取排序字段。 |
| Comparator接口 | Comparator.comparingDouble(...).reversed() 实现双重排序。 |
| 异常处理/边界 | 代码中限制了 scores.size() < 3 的情况,避免除零异常。 |
| 格式化输出 | 使用 Math.round 和拼接字符串控制输出格式。 |
额外思考(如果你想进一步优化)
如果这是面试场景,你可以主动提及以下几点来加分:
- 扩展性:如果评委人数不固定(有时5个、有时8个),用
List存储比用数组更灵活。 - 完整性:如果选手分数为空,
getFinalScore()返回的默认值应该定义为一个常量,而不是魔法数字0。 - 并发安全:如果是高并场景(如实时投票),可以使用
CopyOnWriteArrayList或Collections.synchronizedList,但在当前单线程模拟中不需要。
这个案例逻辑清晰,不仅回答“谁有机会晋级”,还能展示你对编程范式(Stream)和业务建模的熟练程度,你可以直接复制代码运行,或者根据自己的需求修改分组比例。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播