您的位置:首页 >Java读取外部文件数据并按类别分组方法
发布于2026-04-13 阅读(0)
扫一扫,手机访问

本文讲解如何从文本文件中读取拳击选手数据,按体重级别(如 flyweight、featherweight)分类,并分别提取各组最高分选手——使用 Java 8+ Stream API 和面向对象设计实现高效、可维护的解决方案。
本文讲解如何从文本文件中读取拳击选手数据,按体重级别(如 flyweight、featherweight)分类,并分别提取各组最高分选手——使用 Java 8+ Stream API 和面向对象设计实现高效、可维护的解决方案。
在实际开发中,从外部文件(如 boxingcompetition.txt)动态构建结构化数据是常见需求。与其手动维护多个独立数组(如 flyweightScores[] 和 featherweightScores[]),更推荐采用面向对象建模 + 集合分组 + 函数式处理的方式,兼顾可扩展性与代码清晰度。
✅ Boxer 必须可比较:compareTo() 方法应按 score 降序排列(返回 other.score - this.score 实现升序;当前示例中 this.score - other.score 实际为升序,但输出结果表明逻辑已适配最大值获取——更稳妥写法是显式使用 Comparator.comparingInt(Boxer::getScore).reversed()):
// 推荐写法:明确语义,避免歧义
@Override
public int compareTo(Boxer other) {
return Integer.compare(other.score, this.score); // 降序:高分在前
}✅ 健壮的文件读取:使用 getResourceAsStream() 加载 classpath 下资源(如 src/main/resources/boxingcompetition.txt),注意首行 competition 数值仅作提示,真实数据行数由文件内容决定,不应硬编码循环次数(原问题中 totalCompetition = competition * 2 易出错,应以 hasNextLine() 动态判断)。
✅ 分组后提取每类 Top 1:
Map<String, List<Boxer>> grouped = boxers.stream()
.collect(Collectors.groupingBy(Boxer::getDivision));
List<Boxer> topPerDivision = grouped.values().stream()
.map(list -> list.stream()
.max(Comparator.comparingInt(Boxer::getScore))
.orElse(null)) // 处理空列表边界情况
.filter(Objects::nonNull)
.collect(Collectors.toList());import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;
public class BoxingAnalyzer {
public static void main(String[] args) {
List<Boxer> allBoxers = parseFile("/boxingcompetition.txt");
// 按体重级别分组,并取每组最高分选手
Map<String, Boxer> topByDivision = allBoxers.stream()
.collect(Collectors.toMap(
Boxer::getDivision,
boxer -> boxer,
(b1, b2) -> b1.getScore() >= b2.getScore() ? b1 : b2 // 同级别保留高分者
));
topByDivision.forEach((div, boxer) ->
System.out.printf("%s: %s (%d points)%n", div, boxer.getName(), boxer.getScore())
);
}
private static List<Boxer> parseFile(String path) {
List<Boxer> boxers = new ArrayList<>();
try (Scanner scan = new Scanner(Objects.requireNonNull(
BoxingAnalyzer.class.getResourceAsStream(path)))) {
if (scan.hasNextLine()) scan.nextLine(); // 跳过首行 competition 计数(非必要)
while (scan.hasNextLine()) {
String line = scan.nextLine().trim();
if (line.isEmpty()) continue;
String[] parts = line.split("\\s*,\\s*"); // 更鲁棒的逗号分割(忽略空格)
if (parts.length < 3) continue;
boxers.add(new Boxer(
parts[0].trim(),
parts[2].trim(),
Integer.parseInt(parts[1].trim())
));
}
} catch (Exception e) {
throw new RuntimeException("Failed to read boxing data", e);
}
return boxers;
}
private static class Boxer {
private final String name, division;
private final int score;
Boxer(String name, String division, int score) {
this.name = name;
this.division = division;
this.score = score;
}
String getName() { return name; }
String getDivision() { return division; }
int getScore() { return score; }
@Override
public String toString() {
return String.format("%s (%s): %d", name, division, score);
}
}
}通过该方案,你不仅解决了“为不同级别创建数组”的表层需求,更建立了可复用的数据处理骨架——未来新增 lightweight 或 heavyweight 类别,代码零修改即可支持。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9