如何将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
相关产品推荐
相关产品推荐

