Java写入CSV时校验行ID与另一CSV ID列匹配的实现方法
ID匹配校验的落地实现
核心优化思路
不要在遍历data每一行时嵌套循环遍历value集合做ID比对,这种写法在数据量较大时性能极差。正确的流程是提前批量提取value集合的所有ID做缓存,再逐行做快速匹配判断,整体流程的时间复杂度能从O(n*m)降到O(n+m)。
分步骤实现细节
- 固定ID列索引
因为两个数据集都是List<List<String>>结构,子列表的元素顺序完全和CSV的列顺序对应,需要先根据实际CSV的表头定义,确定data集合里ID所在的列序号、value集合里ID所在的列序号,定义成常量避免硬编码出错。 - 构建ID匹配缓存池
拿到value集合后,一次性遍历所有有效数据行(跳过表头),把每行对应的ID值提取出来存入HashSet,利用Set的O(1)查找特性快速完成匹配判断。这里需要对提取的ID做trim()处理,避免前后空格导致的格式匹配失效。 - 遍历写入时加校验
逐行处理data的每行数据时,先取出当前行的ID值,判断是否存在于之前构建的ID缓存池中,匹配通过的行才执行写入操作,未匹配的行可以根据业务需求做跳过、日志记录等处理。 - 边界异常防护
每一行取ID前先判断当前行的列数是否大于ID列索引,避免因为CSV行格式不规范导致索引越界异常。
改造后的参考代码
// 按实际CSV表头调整ID对应的列索引 private static final int DATA_ID_COLUMN_INDEX = 0; private static final int VALUE_ID_COLUMN_INDEX = 0; // 按实际读取的CSV结构调整跳过的表头行数 private static final int SKIP_HEADER_ROW_COUNT = 1; public void writeRecords(List<List<String>> data) throws IOException { // 用try-with-resources自动管理文件流,避免资源泄漏 try (FileWriter csvWriter1 = new FileWriter(OUTPUT_PATH)) { Cable c1 = new Cable(); List<List<String>> value = c1.readRecords(); // 提前构建value侧的ID匹配缓存 Set<String> validIdPool = new HashSet<>(); for (int i = SKIP_HEADER_ROW_COUNT; i < value.size(); i++) { List<String> valueRow = value.get(i); if (valueRow.size() > VALUE_ID_COLUMN_INDEX) { String rowId = valueRow.get(VALUE_ID_COLUMN_INDEX).trim(); validIdPool.add(rowId); } } // 逐行处理data写入,加入匹配校验 for (List<String> rowData : data) { // 跳过列数不足的异常行 if (rowData.size() <= DATA_ID_COLUMN_INDEX) { continue; } String currentId = rowData.get(DATA_ID_COLUMN_INDEX).trim(); // 匹配通过才写入 if (validIdPool.contains(currentId)) { csvWriter1.append(String.join(",", rowData)); csvWriter1.append("\n"); } else { // 可根据业务补充未匹配行的日志记录逻辑 System.out.printf("未匹配到有效ID,跳过行,当前ID值:%s%n", currentId); } } csvWriter1.flush(); } }
扩展场景说明
- 如果匹配到ID后需要同步读取
value侧对应行的其他字段拼接到输出CSV中,可以把缓存结构从HashSet换成HashMap<String, List<String>>,key存ID值,value存对应的整行数据,匹配命中时可以直接拿到关联的行内容。 - 如果业务需要不区分大小写匹配,可以在提取ID缓存、读取当前行ID时统一转为小写/大写做比对,避免格式差异影响匹配结果。
内容的提问来源于stack exchange,提问作者Shubham Raj
相关产品推荐
相关产品推荐

