综合java案例,谁更有机会晋级?

wen java案例 2

本文目录导读:

综合java案例,谁更有机会晋级?

  1. 业务场景设定
  2. 第一部分:定义选手实体(Player
  3. 第二部分:业务逻辑层(PlayOffService
  4. 第三部分:主程序入口(Main
  5. 运行结果示例(每次都会随机,但逻辑一致)
  6. 这个案例涵盖了哪些核心Java知识点?
  7. 额外思考(如果你想进一步优化)

这是一个非常经典的综合Java案例,考察的是面向对象设计(OOP)、集合框架、Lambda表达式/Stream流、比较器以及业务逻辑的综合运用。

为了让你更直观地理解,我设计了一个“选秀节目晋级系统”的模拟场景。


业务场景设定

某选秀节目有 10 名选手,评委进行打分(满分100分)。 晋级规则(业务逻辑)

  1. 去掉一个最高分,去掉一个最低分(为了公平)。
  2. 计算剩余分数的平均分作为最终得分。
  3. 按照最终得分从高到低排序
  4. 前 40%(即前4名)的选手直接晋级。
  5. 第5名到第7名进入待定区(有复活机会)。
  6. 后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 APIComparator 进行复杂的数据处理与分析。

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 类封装数据与行为(addScoregetFinalScore)。
集合框架 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 和拼接字符串控制输出格式。

额外思考(如果你想进一步优化)

如果这是面试场景,你可以主动提及以下几点来加分:

  1. 扩展性:如果评委人数不固定(有时5个、有时8个),用 List 存储比用数组更灵活。
  2. 完整性:如果选手分数为空,getFinalScore() 返回的默认值应该定义为一个常量,而不是魔法数字 0
  3. 并发安全:如果是高并场景(如实时投票),可以使用 CopyOnWriteArrayListCollections.synchronizedList,但在当前单线程模拟中不需要。

这个案例逻辑清晰,不仅回答“谁有机会晋级”,还能展示你对编程范式(Stream)和业务建模的熟练程度,你可以直接复制代码运行,或者根据自己的需求修改分组比例。

抱歉,评论功能暂时关闭!