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

Java诊疗数据导入与Wizyty对象构建及设计问题咨询

问题描述

我正在开发一个程序,需导入Doctor、Patient、Visits三个文本文件,实现患者与医生关联并构建Wizyty对象。当前问题是:导入Visits文件创建Wizyty对象时,会直接读取任意医生ID和患者ID,需添加校验逻辑,确保同一行的医生ID和患者ID真实存在后再构建对象。

现有Java代码如下:

public static void main(String[] args) {

    List<Lekarz> lekarz = new ArrayList<>();

    try {
        File fileLekarze = new File("src/com/company/lekarze.txt");
        Scanner readerLekarze = new Scanner(fileLekarze);
        readerLekarze.nextLine();
        while (readerLekarze.hasNextLine()) {
            String[] data = readerLekarze.nextLine().trim().split("\t+");
            lekarz.add(new Lekarz(Integer.parseInt(data[0]), data[1], data[2], data[3], new SimpleDateFormat("yyyy-MM-dd").parse(data[4]), data[5], data[6]));
        }
        readerLekarze.close();

    } catch (FileNotFoundException e) {
        System.out.println("Error File Lekarze");
        e.printStackTrace();
    } catch (ParseException e) {
        e.printStackTrace();
    }


    List<Pacjenci> pacjent = new ArrayList<>();

    try {
        File pacjenciFile = new File("src/com/company/pacjenci.txt");
        Scanner readerPacjenci = new Scanner(pacjenciFile);
        readerPacjenci.nextLine();
        while (readerPacjenci.hasNextLine()) {
            String[] data = readerPacjenci.nextLine().trim().split("\t");
            pacjent.add(new Pacjenci(Integer.parseInt(data[0]), data[1], data[2], data[3], new SimpleDateFormat("yyyy-MM-dd").parse(data[4])));
        }
        readerPacjenci.close();


    } catch (FileNotFoundException e) {
        System.out.println("Error File Pacjenci");
        e.printStackTrace();
    } catch (ParseException e) {
        e.printStackTrace();
    }


    List<Wizyty> wizytyList = new ArrayList<>();

    try {
        File fileWizyty = new File("src/com/company/wizyty.txt");
        Scanner readerWizyty = new Scanner(fileWizyty);
        readerWizyty.nextLine();
        while (readerWizyty.hasNextLine()) {
            String[] data = readerWizyty.nextLine().trim().split("\t");

            Lekarz lekarz1 = lekarz.stream()
                    .filter(m -> m.getIdLekarza() == Integer.parseInt(data[0]))
                    .findAny()
                    .orElse(null);

            Pacjenci pacjenci1 = pacjent.stream()
                    .filter(m -> m.getIdPacjenta() == Integer.parseInt(data[1]))
                    .findAny()
                    .orElse(null);

            Wizyty wizyta = new Wizyty(Integer.parseInt(data[0]), Integer.parseInt(data[1]), new SimpleDateFormat("yyyy-MM-dd").parse(data[2]));

            wizytyList.add(wizyta);
        }
        readerWizyty.close();
    } catch (FileNotFoundException e) {
        System.out.println("Error File Wizyty");
        e.printStackTrace();
    } catch (ParseException e) {
        e.printStackTrace();
    }
    System.out.println(wizytyList);
}

文本文件格式

  • Visits文件(wizyty.txt):
Id_lekarza  Id_pacjenta Data_wizyty
  23             124     2006-12-13
  23             172     2006-1-25
  • Doctor文件(lekarze.txt):
Id_lekarza  Nazwisko    Imie    Specjalnosc Data_urodzenia  NIP PESEL
  23           Kadaj    Monika  laryngolog  1965-03-16   879-122-69-94  65031687654
  • Patient文件(pacjenci.txt):
Id_pacjenta Nazwisko    Imie    PESEL   Data_urodzenia
     100    Kowal     Waldemar  01211309876 2001-1-13

疑问点

  1. 已从Wizyty的构造器中移除了Doctor和Patient对象,此做法是否合理?是否应保留并使用继承?
  2. 如何修改现有代码,使用真实的Lekarz和Pacjenci对象来构建Wizyty对象?
  3. 后续需开发统计患者就诊次数、医生接诊量排名等功能,能否给出相关建议?

解答

1. 构造器移除对象的合理性与继承问题

  • 只存ID不关联真实对象的做法不合理。后续做统计时,每次都要通过ID去查询对应的医生/患者对象,不仅效率低,代码也会冗余。直接关联真实对象能让Wizyty的语义更清晰:一次就诊是「具体的医生」和「具体的患者」在某天的互动,而非两个ID的无意义组合。
  • 不需要使用继承。继承是「is-a」(是一种)关系,Wizyty既不是医生也不是患者,它和两者是「has-a」(拥有)的关联关系,所以应该在Wizyty中持有Lekarz和Pacjenci的引用,而非继承。

2. 修改代码用真实对象构建Wizyty并添加校验

首先调整Wizyty类的构造器,让它接收真实的医生、患者对象和就诊日期:

public class Wizyty {
    private Lekarz lekarz;
    private Pacjenci pacjent;
    private Date dataWizyty;

    public Wizyty(Lekarz lekarz, Pacjenci pacjent, Date dataWizyty) {
        this.lekarz = lekarz;
        this.pacjent = pacjent;
        this.dataWizyty = dataWizyty;
    }

    // 提供getter方法,后续统计功能需要用到
    public Lekarz getLekarz() { return lekarz; }
    public Pacjenci getPacjent() { return pacjent; }
    public Date getDataWizyty() { return dataWizyty; }
}

然后修改主方法中读取Wizyty的逻辑,添加校验(只有医生和患者都存在时才创建对象),同时用Map存储ID与对象的映射提升查找效率:

List<Wizyty> wizytyList = new ArrayList<>();
// 将医生和患者列表转为ID映射的Map,避免每次遍历列表查询
Map<Integer, Lekarz> lekarzMap = lekarz.stream()
        .collect(Collectors.toMap(Lekarz::getIdLekarza, l -> l));
Map<Integer, Pacjenci> pacjentMap = pacjent.stream()
        .collect(Collectors.toMap(Pacjenci::getIdPacjenta, p -> p));

try {
    File fileWizyty = new File("src/com/company/wizyty.txt");
    Scanner readerWizyty = new Scanner(fileWizyty);
    readerWizyty.nextLine(); // 跳过表头
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    
    while (readerWizyty.hasNextLine()) {
        String[] data = readerWizyty.nextLine().trim().split("\\s+"); // 用空白分割,兼容多个制表符/空格
        int lekarzId = Integer.parseInt(data[0]);
        int pacjentId = Integer.parseInt(data[1]);
        Date dataWizyty = sdf.parse(data[2]);
        
        // 校验医生和患者是否存在
        Lekarz existingLekarz = lekarzMap.get(lekarzId);
        Pacjenci existingPacjent = pacjentMap.get(pacjentId);
        
        if (existingLekarz != null && existingPacjent != null) {
            wizytyList.add(new Wizyty(existingLekarz, existingPacjent, dataWizyty));
        } else {
            // 打印无效记录日志,跳过错误数据
            System.out.printf("无效就诊记录:医生ID %d 或患者ID %d 不存在%n", lekarzId, pacjentId);
        }
    }
    readerWizyty.close();
} catch (FileNotFoundException e) {
    System.out.println("Error File Wizyty");
    e.printStackTrace();
} catch (ParseException e) {
    System.out.println("日期解析错误");
    e.printStackTrace();
}

3. 统计功能开发建议

患者就诊次数统计

用Map存储患者与就诊次数的映射,通过流式API分组统计:

Map<Pacjenci, Long> pacjentWizytyCount = wizytyList.stream()
        .collect(Collectors.groupingBy(Wizyty::getPacjent, Collectors.counting()));

// 打印统计结果
pacjentWizytyCount.forEach((pacjent, count) -> 
        System.out.printf("患者 %s %s 就诊次数:%d%n", pacjent.getImie(), pacjent.getNazwisko(), count));

医生接诊量排名

先分组统计接诊次数,再按次数降序排序:

List<Map.Entry<Lekarz, Long>> lekarzRanking = wizytyList.stream()
        .collect(Collectors.groupingBy(Wizyty::getLekarz, Collectors.counting()))
        .entrySet()
        .stream()
        .sorted(Map.Entry.<Lekarz, Long>comparingByValue().reversed())
        .collect(Collectors.toList());

// 打印排名
System.out.println("医生接诊量排名:");
int rank = 1;
for (Map.Entry<Lekarz, Long> entry : lekarzRanking) {
    Lekarz l = entry.getKey();
    System.out.printf("%d. %s %s(%s):%d 次%n", rank++, l.getImie(), l.getNazwisko(), l.getSpecjalnosc(), entry.getValue());
}

额外优化建议

  • 替换SimpleDateFormat为Java 8+的LocalDate和DateTimeFormatter,线程安全且API更友好。
  • 将文件读取逻辑封装成独立工具方法(比如loadLekarzeFromFile、loadPacjenciFromFile),让主方法更简洁。
  • 添加异常细化处理,比如捕获NumberFormatException,避免因文件中ID不是数字导致程序崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:39:20