MongoDB Java中Iterable<Entity>转List的高效方法及性能问题求解
Iterable转List最高效方案及性能问题排查
当前代码的性能瓶颈
你耗时高的核心原因是对Mongo返回的Iterable错误使用了并行流:MongoDB驱动返回的Iterable实现类的Spliterator不支持高效的并行拆分,并行流带来的线程调度、上下文切换开销远高于多线程处理的收益,尤其是在IO后处理场景下,并行属于典型的负优化。
此外Collectors.toList()默认创建的ArrayList没有预设初始容量,8万条数据会触发多次扩容拷贝,也会增加额外开销。
最高效的转换方案(按性能从高到低排序)
1. 直接使用Mongo驱动自带的into方法(最优)
官方Mongo驱动的MongoIterable原生提供了批量导入集合的方法,没有额外的Stream封装开销,性能最高:
// 提前按预估返回条数设置ArrayList初始容量,避免扩容 List<TestEntity> testSummary = new ArrayList<>(85000); entityResult.into(testSummary);
2. 手动遍历Iterable写入预分配容量的List
性能和into方法基本一致,兼容性更好:
List<TestEntity> testSummary = new ArrayList<>(85000); for (TestEntity entity : entityResult) { testSummary.add(entity); }
3. 若必须使用Stream,关闭并行模式
把并行流的第二个参数改为false,避免不必要的并行开销,同时指定预分配容量的List接收结果:
List<TestEntity> testSummary = StreamSupport.stream(entityResult.spliterator(), false) .collect(Collectors.toCollection(() -> new ArrayList<>(85000)));
两个集合耗时差异的原因
你慢的集合1比集合2多了bLocation地理位置数组字段,单条实体的序列化、反序列化开销本身就更高,再加上8万条数据量是3万条的2.6倍,在并行流的开销放大下就出现了15秒的耗时。
如果不需要返回所有字段,可以在查询时增加projection只返回业务需要的字段,进一步降低反序列化开销,提升转换速度。
内容的提问来源于stack exchange,提问作者DevToCode
相关产品推荐
相关产品推荐

