本文详解 java 中读取文件整数并去重存入数组的实现方法,重点解决因布尔变量作用域错误导致的重复判断失效问题,并提供健壮、可复用的代码方案。
本文详解 java 中读取文件整数并去重存入数组的实现方法,重点解决因布尔变量作用域错误导致的重复判断失效问题,并提供健壮、可复用的代码方案。
在 Java 中从文件读取整数并仅保留唯一值填充目标数组,是一个常见但易出错的任务。核心挑战在于:如何准确识别并跳过已存在的重复值。原代码逻辑本身合理——遍历已填充部分(list[0..size-1])检查新读取值是否已存在;但关键缺陷在于 boolean ID = false 被声明在 while 循环外部,导致一旦某次检测到重复,ID 保持 true 状态直至下次显式重置,从而错误地将后续所有合法新值判定为重复。
✅ 正确做法:限定布尔标志的作用域
必须将 ID 声明移至 while 循环内部(即每次处理一个新数值前),确保其每次初始化为 false,独立标记当前值是否为重复:
private static int read(String inFileName, int[] list) {
int size = 0;
Scanner inFile = null;
int trash = 0, unique = 0, dupe = 0, lineCount = 0;
try {
inFile = new Scanner(new File(inFileName));
while (inFile.hasNext()) {
lineCount++;
boolean isDuplicate = false; // ✅ 关键修复:每次循环新建,确保初始为 false
try {
int val = inFile.nextInt();
if (val < 0) {
trash++;
continue;
}
// 检查是否已在 list[0..size-1] 中存在
for (int i = 0; i < size; i++) {
if (list[i] == val) {
isDuplicate = true;
dupe++;
break; // ✅ 找到即退出,提升效率
}
}
// 仅当非重复且数组未满时添加
if (!isDuplicate && size < list.length) {
list[size] = val;
size++;
unique++;
}
} catch (InputMismatchException e) {
trash++;
inFile.nextLine(); // 清除错误行,避免死循环
}
}
System.out.printf("Lines: %d | Unique: %d | Duplicates: %d | Invalid/Negative: %d%n",
lineCount, unique, dupe, trash);
} catch (FileNotFoundException e) {
System.err.println("Error: Cannot open file '" + inFileName + "'");
return 0;
} finally {
if (inFile != null) inFile.close(); // ✅ 防止资源泄漏
}
return size;
}? 关键改进说明
- 作用域修正:isDuplicate 在每次迭代开始时重新声明,彻底消除状态残留问题;
- 提前终止:break 语句在发现重复后立即退出内层循环,避免冗余比较;
- 资源安全:finally 块中关闭 Scanner,符合 Java 最佳实践;
- 输出优化:使用 printf 提升日志可读性,并区分“无效/负数”与“重复”两类丢弃数据;
- 命名规范:采用 isDuplicate(驼峰命名+布尔语义)替代模糊的 ID,增强可维护性。
⚠️ 注意事项与扩展建议
- 数组容量限制:当前逻辑在 size 动态扩容,或抛出 IllegalArgumentException 明确提示。
-
性能考量:对大量数据,O(n²) 的线性查找效率较低。可升级为 HashSet
缓存已见值,将查重复杂度降至 O(1): Set<Integer> seen = new HashSet<>(); // ... 在循环内替换为:if (seen.add(val)) { /* 新值,存入数组 */ } - 输入鲁棒性:当前仅跳过负数和格式异常,如需支持浮点数、空行、注释等,应增强解析逻辑或使用更成熟的 CSV 解析库。
该方案直击原始 bug 根源,兼顾正确性、可读性与工程健壮性,适用于教学及中小型数据去重场景。










