如何用Java Stream从文件读取数组并填充Student类marks字段?
问题描述
我有一个Student类,其中marks字段为数组类型,需要从文件中读取数据来填充该类的所有字段,且要求通过Java Stream实现。目前编写的代码存在问题,希望了解更简便的Stream实现方式,或是如何修复现有代码。
现有代码
class Lesson_Stream6 { // # Name Surname Marks // 1 Mike Scott [4,5,5] // 2 Joe Jones [1,2,3] // 3 Ann Fleming [3,3,3] public static void main(String[] args) { String path1 = "C:\\Users\\Professional\\IdeaProjects\\Lesson\\src\\StreamAPI\\FileStream"; List<String> fileLineName = new ArrayList<>(); List<String> fileLineNameSurname = new ArrayList<>(); List<String> stream1 = Files.lines(Paths.get(path1)).toList(); String[] arr = new String[stream1.size()]; for (int i = 0; i < stream1.size(); i++) { arr[i] = stream1.get(i); } List<String>NameSurname = Stream.of(arr) .filter( line -> !line.startsWith("#")) .map( l -> l.split(" ")[1] + l.split(" ")[2]) .collect(Collectors.toList()); List<Student6>student4s = Stream.of(arr) .filter( line -> !line.startsWith("#")) .map( l -> { String s = l.split(" ")[3]; String[] chars = s.split(""); Integer[] integers = new Integer[3]; for (int i = 0; i < chars.length; i++) { if (chars[i].matches("[0-9]")) { int c = 0; integers[c++] = Integer.parseInt(chars[i]); } } out.println(Arrays.toString(integers)); return new Student6(Integer.parseInt(l.split(" ")[0]), l.split(" ")[1], l.split(" ")[2], new Integer[]{1, 1, 1}); }) .collect(Collectors.toList()); out.println(student4s.get(1).Name); } } class Student6 { int ID; String Name; String Surname; Integer [] marks; public Student6(int ID, String name, String surname, Integer[] marks) { this.ID = ID; Name = name; Surname = surname; this.marks = marks; } }
现有代码问题分析
- 冗余操作:将
Files.lines返回的Stream转成List再转数组完全多余,直接使用原始Stream即可。 - Marks处理逻辑错误:循环中
int c = 0;会每次重置索引,导致只有integers[0]能被赋值;且通过拆分字符数组提取数字的方式效率低、逻辑繁琐。 - 重复拆分字符串:多次调用
l.split(" ")会重复创建数组,浪费性能。 - 无效赋值:最终返回
Student6时硬编码了new Integer[]{1,1,1},完全没用到处理后的integers数组。 - 异常未处理:
Files.lines会抛出IO异常,原代码未做捕获处理。
优化后的Stream实现代码
import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; class Lesson_Stream6 { // 文件内容示例: // # Name Surname Marks // 1 Mike Scott [4,5,5] // 2 Joe Jones [1,2,3] // 3 Ann Fleming [3,3,3] public static void main(String[] args) { String path1 = "C:\\Users\\Professional\\IdeaProjects\\Lesson\\src\\StreamAPI\\FileStream"; try { List<Student6> students = Files.lines(Paths.get(path1)) // 跳过注释行 .filter(line -> !line.startsWith("#")) // 单行转换为Student对象,仅拆分一次字符串 .map(line -> { String[] parts = line.split(" "); int id = Integer.parseInt(parts[0]); String name = parts[1]; String surname = parts[2]; // 提取并转换marks数组:去除[]符号后按逗号拆分,转成Integer数组 String marksRaw = parts[3].replaceAll("[\\[\\]]", ""); Integer[] marks = Arrays.stream(marksRaw.split(",")) .map(Integer::parseInt) .toArray(Integer[]::new); return new Student6(id, name, surname, marks); }) .collect(Collectors.toList()); // 测试输出 System.out.println(students.get(1).Name); System.out.println(Arrays.toString(students.get(1).marks)); } catch (Exception e) { e.printStackTrace(); } } } class Student6 { int ID; String Name; String Surname; Integer[] marks; public Student6(int ID, String name, String surname, Integer[] marks) { this.ID = ID; Name = name; Surname = surname; this.marks = marks; } }
优化点说明
- 直接使用
Files.lines生成的Stream,省略冗余的List、数组转换步骤。 - 每行仅执行一次
split(" "),避免重复创建字符串数组。 - 用正则表达式快速去除marks字段的
[]符号,再通过Stream将字符串集合转为Integer数组,逻辑简洁高效。 - 增加IO异常捕获,保证代码健壮性。
- 删除原代码中无实际作用的中间集合。
内容的提问来源于stack exchange,提问作者R Zav
相关产品推荐
相关产品推荐

