如何高效检查BufferedReader读取的行是否包含枚举列表中的字符串
优化方案:将处理逻辑与枚举值绑定
你的当前方案相比最初的if-else已有进步,但仍存在冗余的switch语句,且新增关键词时需要同时修改枚举和switch分支,不符合开闭原则。更优的方式是把处理逻辑直接内聚到枚举类中,让每个枚举实例自己负责对应的行处理,彻底消除switch和重复的遍历判断逻辑。
步骤1:修改枚举类,嵌入处理逻辑
在枚举中定义抽象处理方法,每个枚举实例实现该方法,适配各自的参数需求:
import java.util.Optional; public enum GameFileKeys { ANTE("posts ante") { @Override public void process(String currentLine, Object... args) { playerJoinLate(currentLine); } }, SEAT("Seat ") { @Override public void process(String currentLine, Object... args) { if (args.length > 0 && args[0] instanceof YourTableType[]) { seatAndPlayerAssignment((YourTableType[]) args[0], currentLine); } } }; private final String gameKey; GameFileKeys(String str) { this.gameKey = str; } @Override public String toString() { return gameKey; } // 抽象处理方法,用可变参数适配不同方法的参数差异 public abstract void process(String currentLine, Object... args); // 封装匹配逻辑到枚举内部,简化外部调用 public static Optional<GameFileKeys> findMatchingKey(String line) { for (GameFileKeys key : values()) { if (line.contains(key.gameKey)) { return Optional.of(key); } } return Optional.empty(); } // 若处理方法为外部类成员,可将枚举设为该类内部枚举,或调整访问权限 private void seatAndPlayerAssignment(YourTableType[] currentTableArr, String currentLine) { // 原方法逻辑 } private void playerJoinLate(String currentLine) { // 原方法逻辑 } }
注:将YourTableType替换为你实际的数组类型;如果处理方法属于外部类,可将枚举设为该类的内部枚举,或通过参数传入处理逻辑。
步骤2:简化文件读取逻辑
借助枚举封装的匹配和处理逻辑,读取代码会变得非常简洁:
import java.io.BufferedReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; // ... try (BufferedReader reader = Files.newBufferedReader(inputFile.toPath(), StandardCharsets.UTF_8)) { String currentLine; while ((currentLine = reader.readLine()) != null) { // 找到匹配的枚举值并执行处理 GameFileKeys.findMatchingKey(currentLine) .ifPresent(key -> key.process(currentLine, currentTableArr)); } } catch (Exception e) { // 异常处理逻辑 }
额外优化点
- 指定字符编码:用
Files.newBufferedReader替代FileReader,显式指定UTF-8编码,避免平台默认编码导致的乱码问题。 - 控制匹配顺序:如果一行可能匹配多个关键词,枚举的定义顺序就是遍历匹配的顺序,可根据业务需求调整枚举实例的顺序。
- 函数式接口适配:如果处理方法的参数差异较大,也可以在枚举中存储
BiConsumer等函数式接口,进一步灵活适配:public enum GameFileKeys { ANTE("posts ante", line -> playerJoinLate(line)), SEAT("Seat ", (line, args) -> { if (args[0] instanceof YourTableType[]) { seatAndPlayerAssignment((YourTableType[]) args[0], line); } }); private final String gameKey; private final BiConsumer<String, Object[]> processor; GameFileKeys(String str, BiConsumer<String, Object[]> processor) { this.gameKey = str; this.processor = processor; } public void process(String currentLine, Object... args) { processor.accept(currentLine, args); } // 省略其他重复代码 }
对比优势
- 消除冗余代码:无需维护switch分支,新增关键词时仅需在枚举中添加新实例和处理逻辑。
- 代码内聚性更强:关键词与其处理逻辑绑定,避免分散在不同代码块中。
- 符合开闭原则:新增功能无需修改现有读取逻辑,仅扩展枚举即可。
内容的提问来源于stack exchange,提问作者Another Joe
相关产品推荐
相关产品推荐

