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

如何将ArrayList转换为TreeMap并合理拆分Java代码结构?

如何优雅地拆分代码并将症状列表转换为TreeMap?

嘿,我来帮你优化这个代码结构!你的核心需求是拆分职责(读取、统计、写入、异常处理),同时优雅地把ReadSymptomDataFromFile返回的列表转换成TreeMap统计频率。先说说你当前FileToTreeMap的问题:把ArrayList转成String再用Scanner处理是错误且冗余的——List的toString会生成带[]和逗号的字符串,Scanner会把这些符号当成内容的一部分,导致统计结果出错;而且你完全没必要重新读取文件,直接用ReadSymptomDataFromFile返回的List就好。

咱们按照单一职责原则拆分代码,每个类只做一件事,代码会更整洁优雅:


1. 保留原有的ReadSymptomDataFromFile类

这个类已经实现了读取症状的职责,完全可以复用,不用修改。


2. 新建SymptomCounter类:专门负责统计症状频率

这个类接收症状列表,返回排序好的TreeMap(键是症状,值是出现次数),用Java 8+的merge方法可以大幅简化统计逻辑:

package com.hemebiotech.analytics;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class SymptomCounter {
    // 统计症状频率,返回按自然排序的TreeMap
    public Map<String, Integer> countSymptoms(List<String> symptoms) {
        Map<String, Integer> symptomCounts = new TreeMap<>();
        
        for (String symptom : symptoms) {
            // merge方法:键不存在则存入1,存在则把旧值+1,一行搞定统计
            symptomCounts.merge(symptom, 1, Integer::sum);
        }
        
        return symptomCounts;
    }
}

3. 新建SymptomWriter类:专门负责写入结果文件

用try-with-resources自动管理IO资源,避免忘记关闭流,异常往上抛让调用者统一处理:

package com.hemebiotech.analytics;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;

public class SymptomWriter {
    private final String outputFilePath;

    public SymptomWriter(String outputFilePath) {
        this.outputFilePath = outputFilePath;
    }

    // 写入统计结果到文件,抛出IOException让上层处理
    public void writeSymptoms(Map<String, Integer> symptomCounts) throws IOException {
        // try-with-resources会自动关闭BufferedWriter,无需手动close
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilePath))) {
            for (Map.Entry<String, Integer> entry : symptomCounts.entrySet()) {
                writer.write(entry.getKey() + " = " + entry.getValue());
                writer.newLine(); // 换行更规范
            }
        }
    }
}

4. 主程序MainApp:整合所有组件并处理异常

把各个模块串起来,集中处理异常,控制台输出也更规范:

package com.hemebiotech.analytics;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public class MainApp {
    public static void main(String[] args) {
        // 配置文件路径
        String inputFilePath = "Project02Eclipse\\symptoms.txt";
        String outputFilePath = "resultat2.out";

        try {
            // 步骤1:读取症状列表
            ISymptomReader symptomReader = new ReadSymptomDataFromFile(inputFilePath);
            List<String> symptoms = symptomReader.getSymptoms();

            // 步骤2:统计症状频率
            SymptomCounter counter = new SymptomCounter();
            Map<String, Integer> symptomCounts = counter.countSymptoms(symptoms);

            // 步骤3:控制台输出统计结果
            System.out.println("=== 症状统计结果 ===");
            for (Map.Entry<String, Integer> entry : symptomCounts.entrySet()) {
                // 用printf格式化输出,比字符串拼接更整洁
                System.out.printf("Valeur: %s | Occurence: %d%n", entry.getKey(), entry.getValue());
            }

            // 步骤4:写入结果到文件
            SymptomWriter writer = new SymptomWriter(outputFilePath);
            writer.writeSymptoms(symptomCounts);

            System.out.println("\n结果已成功写入文件:" + outputFilePath);

        } catch (IOException e) {
            // 统一处理IO异常,用System.err输出错误信息
            System.err.println("处理文件时发生错误:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

这样拆分的好处

  • 职责单一:每个类只做一件事,比如SymptomCounter可以复用在任何需要统计字符串频率的场景,不管数据来源是文件还是数据库
  • 代码简洁:用merge方法替代繁琐的containsKey判断,try-with-resources自动管理资源
  • 易维护:如果以后需要更换读取方式(比如从数据库读),只需要实现ISymptomReader接口就行,不用修改统计和写入的代码
  • 异常规范:集中处理异常,避免到处捕获异常导致代码混乱

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 12:22:36