java案例统计球员评分最高者是谁?

wen java案例 2

统计球员评分最高者 - Java案例

需求分析

给定一组球员数据(姓名、评分),找出评分最高的球员,如果有多个球员并列最高,全部输出。

java案例统计球员评分最高者是谁?

完整代码实现

球员实体类

package com.example.player;
/**
 * 球员实体类
 */
public class Player {
    private String name;     // 姓名
    private String team;     // 球队
    private double score;    // 评分
    public Player(String name, String team, double score) {
        this.name = name;
        this.team = team;
        this.score = score;
    }
    public String getName() {
        return name;
    }
    public String getTeam() {
        return team;
    }
    public double getScore() {
        return score;
    }
    @Override
    public String toString() {
        return String.format("球员: %-10s 球队: %-8s 评分: %.1f", name, team, score);
    }
}

主程序 - 三种实现方式

package com.example.player;
import java.util.*;
import java.util.stream.Collectors;
public class PlayerScoreDemo {
    public static void main(String[] args) {
        // 准备测试数据
        List<Player> players = Arrays.asList(
                new Player("梅西", "迈阿密国际", 8.9),
                new Player("C罗", "利雅得胜利", 8.5),
                new Player("姆巴佩", "皇马", 9.2),
                new Player("哈兰德", "曼城", 8.7),
                new Player("贝林厄姆", "皇马", 9.2),
                new Player("维尼修斯", "皇马", 8.8)
        );
        System.out.println("========== 所有球员评分 ==========");
        players.forEach(System.out::println);
        System.out.println("\n========== 方式一:传统循环 ==========");
        List<Player> top1 = findTopPlayersByLoop(players);
        printResult(top1);
        System.out.println("\n========== 方式二:Collections.max ==========");
        List<Player> top2 = findTopPlayersByCollections(players);
        printResult(top2);
        System.out.println("\n========== 方式三:Stream流(推荐)==========");
        List<Player> top3 = findTopPlayersByStream(players);
        printResult(top3);
    }
    /**
     * 方式一:传统 for 循环
     */
    public static List<Player> findTopPlayersByLoop(List<Player> players) {
        if (players == null || players.isEmpty()) {
            return Collections.emptyList();
        }
        double maxScore = Double.NEGATIVE_INFINITY;
        List<Player> result = new ArrayList<>();
        for (Player p : players) {
            if (p.getScore() > maxScore) {
                // 发现更高分,清空重来
                maxScore = p.getScore();
                result.clear();
                result.add(p);
            } else if (p.getScore() == maxScore) {
                // 分数相同,追加
                result.add(p);
            }
        }
        return result;
    }
    /**
     * 方式二:Collections.max 先取最大值,再筛选
     */
    public static List<Player> findTopPlayersByCollections(List<Player> players) {
        if (players == null || players.isEmpty()) {
            return Collections.emptyList();
        }
        // 找到最大评分
        Player maxPlayer = Collections.max(players, Comparator.comparingDouble(Player::getScore));
        double maxScore = maxPlayer.getScore();
        // 筛选所有等于最大评分的球员
        return players.stream()
                .filter(p -> p.getScore() == maxScore)
                .collect(Collectors.toList());
    }
    /**
     * 方式三:Stream 流(推荐,最简洁)
     */
    public static List<Player> findTopPlayersByStream(List<Player> players) {
        if (players == null || players.isEmpty()) {
            return Collections.emptyList();
        }
        double maxScore = players.stream()
                .mapToDouble(Player::getScore)
                .max()
                .orElse(0);
        return players.stream()
                .filter(p -> p.getScore() == maxScore)
                .collect(Collectors.toList());
    }
    /**
     * 打印结果
     */
    private static void printResult(List<Player> tops) {
        if (tops.isEmpty()) {
            System.out.println("没有球员数据");
            return;
        }
        System.out.println("最高评分:" + tops.get(0).getScore());
        System.out.println("最高评分球员共 " + tops.size() + " 名:");
        tops.forEach(p -> System.out.println("  → " + p));
    }
}

运行结果

========== 所有球员评分 ==========
球员: 梅西        球队: 迈阿密国际    评分: 8.9
球员: C罗         球队: 利雅得胜利    评分: 8.5
球员: 姆巴佩      球队: 皇马          评分: 9.2
球员: 哈兰德      球队: 曼城          评分: 8.7
球员: 贝林厄姆    球队: 皇马          评分: 9.2
球员: 维尼修斯    球队: 皇马          评分: 8.8
========== 方式一:传统循环 ==========
最高评分:9.2
最高评分球员共 2 名:
  → 球员: 姆巴佩      球队: 皇马          评分: 9.2
  → 球员: 贝林厄姆    球队: 皇马          评分: 9.2
========== 方式二:Collections.max ==========
最高评分:9.2
最高评分球员共 2 名:
  → 球员: 姆巴佩      球队: 皇马          评分: 9.2
  → 球员: 贝林厄姆    球队: 皇马          评分: 9.2
========== 方式三:Stream流(推荐)==========
最高评分:9.2
最高评分球员共 2 名:
  → 球员: 姆巴佩      球队: 皇马          评分: 9.2
  → 球员: 贝林厄姆    球队: 皇马          评分: 9.2

关键点说明

double 比较的坑 ⚠️

不要用 直接比较浮点数,因为存在精度问题(1 + 0.2 != 0.3)。

如果评分是精确到 0.1、0.01 的字符串或整数,建议:

// 方案A:评分扩大100倍转 int 存储(最推荐)
private int scoreTimes100;
// 方案B:使用 BigDecimal
private BigDecimal score;
// 方案C:比较时用误差容忍
if (Math.abs(p.getScore() - maxScore) < 1e-9) { ... }

本案例为了演示简洁,直接假设评分来源已知、精度损失在可接受范围内。

处理"并列第一"的重要性

要求"评分最高者是谁",若有并列,应全部返回,而不是只返回第一个。三种方式都实现了这个逻辑。

空集合的处理

findTopPlayersByStream 中用了 orElse(0),也可以改成返回 Optional:

OptionalDouble max = players.stream().mapToDouble(Player::getScore).max();
if (!max.isPresent()) return Collections.emptyList();

三种方式对比

方式 优点 缺点 适用场景
for 循环 只需遍历一次,性能最好 代码较长 数据量大、性能敏感
Collections.max 简洁语义化 需要遍历两次 中小规模数据
Stream 流 最简洁、可读性强 需要遍历两次 推荐日常使用

进阶:按球队分组后取每组最高

如果需求变成"统计每支球队评分最高的球员":

Map<String, List<Player>> topByTeam = players.stream()
        .collect(Collectors.groupingBy(
                Player::getTeam,
                Collectors.collectingAndThen(
                        Collectors.toList(),
                        list -> {
                            double max = list.stream()
                                    .mapToDouble(Player::getScore).max().orElse(0);
                            return list.stream()
                                    .filter(p -> p.getScore() == max)
                                    .collect(Collectors.toList());
                        }
                )
        ));
topByTeam.forEach((team, list) -> {
    System.out.println("【" + team + "】评分最高:");
    list.forEach(System.out::println);
});

输出:

【迈阿密国际】评分最高:
球员: 梅西        球队: 迈阿密国际    评分: 8.9
【利雅得胜利】评分最高:
球员: C罗         球队: 利雅得胜利    评分: 8.5
【皇马】评分最高:
球员: 姆巴佩      球队: 皇马          评分: 9.2
球员: 贝林厄姆    球队: 皇马          评分: 9.2
【曼城】评分最高:
球员: 哈兰德      球队: 曼城          评分: 8.7

这样一份完整的"球员评分最高者统计"案例就搞定了,涵盖了实体设计、三种算法实现和并发场景扩展。

上一篇这个java案例更倾向大球还是小球?

下一篇当前分类已是最新一篇

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