Java无内置集合类:学生成绩按GPA升序存入自定义LinkedList的实现
现存代码问题定位
- 数据解析逻辑完全错位:你调试时看到GPA逐次输出1.0、2.0、3.0、4.0,本质是循环自增的
count变量被当作GPA参数传给了Student构造方法;同时把读取到的整行文本直接作为姓名传入,没有拆分每行中独立的姓名、GPA字段,更没有把字符串格式的GPA转换为double类型。 - 类职责严重混淆:把链表节点的
next引用、泛型value字段全部塞到Student数据类中,将“存学生属性的纯数据载体”和“负责链表连接关系的节点”两个逻辑完全混在一起,导致代码结构冗余混乱。 - 自定义LinkedList为空壳:你目前代码中实例化的
LinkedList没有任何存储、插入、排序的实际逻辑,本质是空类,所以直接打印myList只会输出对象哈希值,没有任何实际存储内容。
分步实现合规功能
1. 修正Student类,剥离冗余节点逻辑
Student类只负责存储学生的姓名、GPA属性,删掉所有和链表、泛型相关的多余代码,重写toString方便后续打印验证:
public class Student { private String name; private double gpa; public Student(String name, double gpa) { this.name = name; this.gpa = gpa; } public String getName() { return name; } public double getGpa() { return gpa; } @Override public String toString() { return "姓名:" + name + ",GPA:" + gpa; } }
2. 从零实现自定义LinkedList(完全不依赖Java内置集合类)
链表的核心结构是“头节点标记链表起点 + 每个节点存储实际数据 + 指向下一个节点的引用”,需要单独定义节点的内部类,实现升序插入的核心逻辑:
import java.util.Comparator; // 自定义链表,未使用任何Java内置集合类 public class LinkedList<T> { // 私有内部类:链表节点,只负责存数据、维护下一个节点的连接关系 private class Node { T data; Node next; Node(T data) { this.data = data; this.next = null; } } // 链表的头节点(存储第一个有效元素) private Node head; // 排序比较器,用来指定升序的规则 private Comparator<T> comparator; public LinkedList(Comparator<T> comparator) { this.head = null; this.comparator = comparator; } // 核心方法:按升序规则插入数据,保证链表始终有序 public void addSorted(T newData) { Node newNode = new Node(newData); // 空链表场景:新节点直接作为头节点 if (head == null) { head = newNode; return; } // 新节点值比头节点还小:直接插入到链表最前端 if (comparator.compare(newData, head.data) < 0) { newNode.next = head; head = newNode; return; } // 遍历找到合适的插入位置 Node current = head; while (current.next != null && comparator.compare(newData, current.next.data) > 0) { current = current.next; } // 完成节点连接 newNode.next = current.next; current.next = newNode; } // 遍历打印整个链表的所有元素 public void printAll() { Node current = head; while (current != null) { System.out.println(current.data); current = current.next; } }
排序规则可以灵活调整:如果作业要求按姓名升序,只需要替换比较器的判断逻辑即可,不需要改动链表本身的实现。
3. 修正Driver类的文件读取流程
按照“逐行读取→拆分字段→创建Student对象→按序插入链表”的流程修正代码,用split("\\s+")拆分可以自动适配文件中姓名和GPA之间间隔多空格的场景,不会出现解析错误:
import java.io.*; import java.util.Comparator; public class Driver { private LinkedList<Student> myList; public static void main(String[] args) { new Driver(); } public Driver() { // 初始化链表,指定按GPA升序的规则 myList = new LinkedList<Student>(new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { // 按GPA升序的判断逻辑,如果要按姓名升序,替换为s1.getName().compareTo(s2.getName())即可 return Double.compare(s1.getGpa(), s2.getGpa()); } }); try ( FileInputStream file = new FileInputStream("Student.dat"); BufferedReader read = new BufferedReader(new InputStreamReader(file)) ) { String lineRead; while ((lineRead = read.readLine()) != null) { // 跳过空行 if (lineRead.isBlank()) continue; // 按任意连续空白拆分行内容,自动适配多空格、Tab的分隔场景 String[] parts = lineRead.trim().split("\\s+"); String name = parts[0]; double gpa = Double.parseDouble(parts[1]); // 创建正确的Student对象,调用有序插入方法存入链表 Student newStudent = new Student(name, gpa); myList.addSorted(newStudent); } // 读取完成后打印验证 System.out.println("按GPA升序存储的学生列表:"); myList.printAll(); } catch (IOException e) { e.printStackTrace(); } } }
运行后会输出按GPA从低到高排列的学生列表,完全符合作业的限制要求:没有使用任何Java内置集合类,所有链表逻辑为自行实现,文件解析正确,存储顺序为升序。
内容的提问来源于stack exchange,提问作者Grapefruit889
相关产品推荐
相关产品推荐

