Java实现两个CSV文件按id比对并输出指定列数值差异的方案问询
优化实现方案
核心思路是用id+subId作为联合唯一主键映射对应行的数值,直接消除多层嵌套集合的复杂逻辑,查找效率为O(1),实现非常简洁。
前置设计
因为匹配规则是id和subId联合唯一,所以直接用二者作为Map的键,对应值存储c、d两列的数值即可:
- 优先用Java 16+的
record定义不可变对象,自动生成equals/hashCode,无需手动重写 - 数值类型用
BigDecimal避免浮点运算精度丢失
// 联合主键:id + subId record RecordKey(String id, String subId) {} // 对应行的c、d列数值 record ColumnPair(BigDecimal c, BigDecimal d) {}
如果是Java 16以下版本,手动写普通类重写equals和hashCode方法即可。
完整实现代码
import java.io.IOException; import java.math.BigDecimal; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; public class CsvComparator { public static void main(String[] args) throws IOException { // 读取两个CSV文件存入Map Map<RecordKey, ColumnPair> csv1Map = readCsv("csv1.csv"); Map<RecordKey, ColumnPair> csv2Map = readCsv("csv2.csv"); // 遍历匹配计算差值 for (Map.Entry<RecordKey, ColumnPair> entry : csv1Map.entrySet()) { RecordKey key = entry.getKey(); ColumnPair csv1Val = entry.getValue(); ColumnPair csv2Val = csv2Map.get(key); // 跳过仅在单个CSV存在的key,可按需增加提示 if (csv2Val == null) continue; // 计算差值(取绝对值,保留两位小数) BigDecimal diffC = csv2Val.c().subtract(csv1Val.c()).abs().setScale(2); BigDecimal diffD = csv2Val.d().subtract(csv1Val.d()).abs().setScale(2); // 按要求格式输出 System.out.printf("difference of column c of id %s and sub id %s is : %.2f%n", key.id(), key.subId(), diffC); System.out.printf("difference of column d of id %s and sub id %s is : %.2f%n%n", key.id(), key.subId(), diffD); } } // 读取CSV文件转为Map结构 private static Map<RecordKey, ColumnPair> readCsv(String filePath) throws IOException { Map<RecordKey, ColumnPair> map = new HashMap<>(); Files.lines(Paths.get(filePath)) .filter(line -> !line.isBlank()) // 跳过空行 .forEach(line -> { String[] parts = line.split(","); RecordKey key = new RecordKey(parts[0], parts[1]); BigDecimal c = new BigDecimal(parts[2]); BigDecimal d = new BigDecimal(parts[3]); map.put(key, new ColumnPair(c, d)); }); return map; } }
方案优势
- 结构简单:仅需单层级Map结构,无多层嵌套,逻辑可读性极强
- 效率更高:HashMap的匹配查找为O(1),远高于遍历List匹配的O(n)效率
- 精度可控:用BigDecimal存储运算,完全避免浮点精度丢失问题
内容的提问来源于stack exchange,提问作者Eban Batuta
相关产品推荐
相关产品推荐

