如何用Java Parallel Stream并行读取POI Sheet统计代码出现次数
使用Parallel Stream优化POI Sheet第一列整数代码的统计效率
直接上可运行的实现方案,核心是将POI的行迭代器转为并行流,配合合适的收集器完成统计:
完整代码实现
import org.apache.poi.ss.usermodel.*; import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import java.util.Spliterators; // 假设已通过POI加载得到Sheet实例 Sheet sheet = ...; // 将Row迭代器转为并行流 Stream<Row> rowParallelStream = StreamSupport.stream( Spliterators.spliteratorUnknownSize(sheet.rowIterator(), Spliterator.ORDERED), true // 开启并行模式 ); // 统计第一列整数代码的出现次数 Map<Integer, Long> codeCountMap = rowParallelStream // 跳过表头(如果第0行是表头则加此行,无表头则删除) .skip(1) // 过滤掉第一列单元格为空的行 .filter(row -> row.getCell(0) != null) // 提取第一列的整数,处理不同单元格类型 .map(row -> { Cell cell = row.getCell(0); switch (cell.getCellType()) { case NUMERIC: return (int) cell.getNumericCellValue(); case STRING: try { return Integer.parseInt(cell.getStringCellValue().trim()); } catch (NumberFormatException e) { return null; // 非整数内容后续过滤 } default: return null; // 布尔、公式等类型直接跳过 } }) // 过滤掉转换失败的无效数据 .filter(Objects::nonNull) // 并行收集统计结果,用并发Map提升效率 .collect(Collectors.groupingByConcurrent( Function.identity(), Collectors.counting() )); // 遍历输出统计结果 codeCountMap.forEach((code, count) -> System.out.printf("代码 %d 出现 %d 次%n", code, count));
关键细节说明
- 迭代器转并行流:利用
StreamSupport.stream将POI的RowIterator转为Stream,第二个参数设为true开启并行。 - 单元格类型兼容:覆盖了数值型和文本型的整数场景,避免因单元格格式不同导致的转换失败;对于非整数内容直接过滤。
- 高效收集器选择:使用
groupingByConcurrent替代普通groupingBy,并行流场景下能减少线程间的竞争,提升收集效率。 - 空值与无效数据处理:通过
filter提前过滤空单元格和转换失败的数据,避免后续操作抛出异常。
额外提示
虽然你的数据量在80-400条之间,并行流的线程调度开销可能会抵消部分性能收益,但这个实现方式完全符合你的需求;如果后续数据量增长到数千条以上,并行流的优势会更明显。
内容的提问来源于stack exchange,提问作者MakdaMujji
相关产品推荐
相关产品推荐

