You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java控制台应用中Scanner触发NoSuchElementException问题求助

问题分析与解决方案

问题根源

选择选项2时抛出NoSuchElementException的核心原因是:你在AppointmentsSorter.getSortedList()方法中关闭了绑定System.in的Scanner。System.in是全局唯一的标准输入流,一旦被关闭,后续所有依赖它的输入操作(比如主菜单循环里的sc.nextLine())都会因流已关闭、无元素可读而抛出异常。

解决方案

避免在子模块中关闭关联System.in的Scanner,统一使用一个全局Scanner实例贯穿整个控制台流程,仅在程序完全结束时关闭一次。具体修改如下:

1. 修改主菜单方法,传递全局Scanner

public void selectOption(int doctorID) {
    Scanner sc = new Scanner(System.in);
    String option;
    do {
        System.out.println("Chose one from the options(write only the number):");
        System.out.println("1. Show all appointments for a doctor.");
        System.out.println("2. Sort  all appointments for a doctor.");
        System.out.println("3. Group patients.");
        System.out.println("4. Exit.");
        option = sc.nextLine();
        while (true) {
            if (option.equals("1")) {
                int newID = changeDoctorID(doctorID);
                showAllAppointments(newID);
                break;
            } else if (option.equals("2")) {
                int newID = changeDoctorID(doctorID);
                // 将全局Scanner传递给排序方法
                sortAllAppointments(newID, sc);
                break;
            } else if (option.equals("3")) {
                groupPatients(doctorID);
                break;
            } else if (option.equals("4")) {
                break;
            } else {
                System.out.println("Invalid input! Write only the number:");
                option = sc.nextLine();
            }
        }
    } while (!option.equals("4"));
    // 仅在程序退出时关闭一次Scanner
    sc.close();
}

2. 修改排序类,移除内部Scanner创建与关闭

import java.util.*;

public class AppointmentsSorter {
    private final String appointmentFileName;
    private final String doctorFileName;
    private final String patientFileName;
    private final int doctorID;

    public AppointmentsSorter(String appointmentFileName, String doctorFileName, String patientFileName, int doctorID) {
        this.appointmentFileName = appointmentFileName;
        this.doctorFileName = doctorFileName;
        this.patientFileName = patientFileName;
        this.doctorID = doctorID;
    }

    // 改为接收外部传入的Scanner,不再内部创建
    public List<Appointment> getSortedList(Scanner sc) {
        String option = getSortingOption(sc);
        List<Appointment> sortedAppointmentList;
        if (option.equals("1")) {
            sortedAppointmentList = makeAppointmentListIncreasingOrDecreasingOrder(getSortedAppointmentListByPatientName(), sc);
        } else if (option.equals("2")) {
            sortedAppointmentList = makeAppointmentListIncreasingOrDecreasingOrder(getSortedAppointmentListByDateTime(), sc);
        } else {
            sortedAppointmentList = makeAppointmentListIncreasingOrDecreasingOrder(getSortedAppointmentListByPatientID(), sc);
        }
        // 移除sc.close(),避免关闭System.in
        return sortedAppointmentList;
    }

    // 其余方法保持不变,因为它们已经依赖传入的Scanner参数
    private List<Appointment> getSortedAppointmentListByPatientName() {
        return new ArrayList<>();
        // 实现逻辑
    }

    private List<Appointment> getSortedAppointmentListByPatientID() {
        CSVReader reader = new CSVReader();
        List<Appointment> allAppointmentsList = reader.readAppointmentList(this.appointmentFileName);
        List<Appointment> currentDoctorAppointmentsList = allAppointmentsList.stream()
                .filter(appointment -> appointment.getDoctorID() == this.doctorID).toList();
        List<Appointment> sortedCurrentDoctorAppointmentsList = currentDoctorAppointmentsList.stream()
                .sorted(Comparator.comparing(Appointment::getPatientID)).toList();
        return sortedCurrentDoctorAppointmentsList;
    }

    private List<Appointment> getSortedAppointmentListByDateTime() {
        CSVReader reader = new CSVReader();
        List<Appointment> allAppointmentsList = reader.readAppointmentList(this.appointmentFileName);
        List<Appointment> currentDoctorAppointmentsList = allAppointmentsList.stream()
                .filter(appointment -> appointment.getDoctorID() == this.doctorID).toList();
        Comparator<Appointment> compareByDateAndTime = Comparator.comparing(Appointment::getDate).thenComparing(Appointment::getTime);
        List<Appointment> sortedCurrentDoctorAppointmentsList = currentDoctorAppointmentsList.stream().sorted(compareByDateAndTime).toList();
        return sortedCurrentDoctorAppointmentsList;
    }

    private List<Appointment> makeAppointmentListIncreasingOrDecreasingOrder(List<Appointment> appointmentList, Scanner sc) {
        System.out.println("Select order - increasing or decreasing: ");
        String order = sc.nextLine();
        while (true) {
            if (order.equalsIgnoreCase("increasing")) {
                return appointmentList;
            } else if (order.equalsIgnoreCase("decreasing")) {
                List<Appointment> reversedAppointmentList = new ArrayList<>(appointmentList);
                Collections.reverse(reversedAppointmentList);
                return reversedAppointmentList;
            } else {
                System.out.println("Invalid order! Enter again(increasing or decreasing): ");
                order = sc.nextLine();
            }
        }
    }

    private String getSortingOption(Scanner sc) {
        System.out.println("Sort appointments by(enter only the number): ");
        System.out.println("1. by patient name   2. by date   3. patient ID");
        String option = sc.nextLine();
        while (true) {
            if (option.equals("1") || option.equals("2") || option.equals("3")) {
                return option;
            } else {
                System.out.println("Invalid option! Enter again: ");
                option = sc.nextLine();
            }
        }
    }

    private List<Patient> getPatientListFromAppointments() {
        CSVReader reader = new CSVReader();
        List<Appointment> appointmentList = reader.readAppointmentList(this.appointmentFileName);
        List<Integer> patientIDList = appointmentList.stream().map(Appointment::getPatientID).toList();
        List<Patient> patientList = reader.readPatientList(this.patientFileName);
        List<Patient> filteredPatientList = new ArrayList<>();
        for (int patientID : patientIDList) {
            for (Patient patient : patientList) {
                if (patient.getPatientID() == patientID && !filteredPatientList.contains(patient)) {
                    filteredPatientList.add(patient);
                }
            }
        }
        return filteredPatientList;
    }

    private String getPatientFullName(int patientId, List<Patient> patientList) {
        for (Patient patient : patientList) {
            if (patient.getPatientID() == patientId) {
                return patient.getFirstName() + "" + patient.getLastName();
            }
        }
        return "";
    }
}

3. 修改sortAllAppointments方法,接收并传递Scanner

private void sortAllAppointments(int doctorID, Scanner sc) {
    AppointmentsSorter sorter = new AppointmentsSorter("appointments.csv", "doctors.csv", "patients.csv", doctorID);
    List<Appointment> sortedList = sorter.getSortedList(sc);
    // 后续处理排序结果的逻辑
}

关键说明

  • System.in是全局单例流,关闭后无法重新打开,任何尝试读取已关闭流的操作都会抛出NoSuchElementException。
  • 控制台程序中建议只创建一个Scanner实例,负责所有输入操作,仅在程序退出时关闭它。

内容的提问来源于stack exchange,提问作者Todor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 09:27:03