如何高效计算List<String[]>转换为CSV后的总文件大小?
问题描述
我持有List<String[]>类型的csvRows数据行数组,以及String[]类型的csvHeaderRow表头数组。目标是计算将这些内容写入最终CSV文件后的总大小,需要累加所有数据内容、表头内容、逗号的总大小,同时csvRows中的大量列可能为null或空值(例如"Rick,,,,15,,4324,,,"),而csvHeaderRow始终是完全填充的。
我可以将所有内容写入ByteArrayOutputStream后计算字节数组长度,但希望编写更高效、简洁的代码。当前代码版本如下:
public long getNumOfFiles(List<String[]> csvRows, String[] csvHeaderRow){ long totalSize = csvRows.stream().mapToLong(i -> { return Stream.of(i).mapToLong(str -> { if (StringUtils.isNotEmpty(str)) { return str.getBytes().length; } return 0L; }).sum(); }).sum(); totalSize = totalSize + Stream.of(csvHeaderRow).mapToLong(str -> str.getBytes().length).sum(); totalSize = totalSize + csvHeaderRow.length * csvRows.size() + 1; // 逗号数量 long numOfFiles = (totalSize / MAX_FILE_SIZE_BYTES) + 1; return numOfFiles; }
请问如何更高效地编写这段代码?
优化方案
现有代码的问题点
- Stream嵌套开销:两层Stream嵌套会带来额外的对象创建和遍历开销,数据量大时效率较低
- 字符集不明确:
str.getBytes()使用平台默认字符集,不同环境下可能导致字节数计算不一致 - 逗号数量计算错误:原代码的逗号计算逻辑仅在特定列数和行数下巧合正确,通用场景下会出错
- 遗漏换行符大小:写入CSV时每行(包括表头)末尾的换行符未计入总大小,导致结果偏小
优化后的代码
import java.nio.charset.StandardCharsets; public long getNumOfFiles(List<String[]> csvRows, String[] csvHeaderRow) { int columnCount = csvHeaderRow.length; int rowCount = csvRows.size(); long totalSize = 0; // 计算表头的字节大小 for (String header : csvHeaderRow) { totalSize += header.getBytes(StandardCharsets.UTF_8).length; } // 计算所有数据行的字节大小 for (String[] row : csvRows) { for (String cell : row) { if (cell != null && !cell.isEmpty()) { totalSize += cell.getBytes(StandardCharsets.UTF_8).length; } } } // 计算逗号总大小:每行有(columnCount - 1)个逗号,共(rowCount + 1)行(表头+数据行) long commaTotal = (long) (columnCount - 1) * (rowCount + 1); totalSize += commaTotal; // 计算换行符总大小:每行结尾1个换行符(\n),共(rowCount + 1)行,UTF-8下占1字节 // 若使用\r\n则改为 *2 long newlineTotal = (long) (rowCount + 1); totalSize += newlineTotal; // 计算文件数量 return (totalSize / MAX_FILE_SIZE_BYTES) + 1; }
优化说明
- 替换Stream为普通循环:避免Stream嵌套的额外开销,遍历效率更高,尤其适合大数据量场景
- 明确指定字符集:使用
StandardCharsets.UTF_8确保字节数计算的一致性,不受平台环境影响 - 修正逗号计算逻辑:根据列数和总行数准确计算逗号总数,避免逻辑错误
- 补充换行符计算:CSV文件每行结尾的换行符是必须的,这里默认使用
\n(1字节),若需要兼容Windows的\r\n可改为乘以2 - 简化代码结构:拆分计算步骤,逻辑更清晰,便于维护和调试
- 减少中间变量操作:直接累加总大小,避免多次赋值带来的冗余
内容的提问来源于stack exchange,提问作者Nila
相关产品推荐
相关产品推荐

