百万级List<Long>分区求最值的高效内存优化方案问询
优化方案:无额外子列表的分区统计
你的核心问题是原方案通过创建子列表分区导致额外内存占用,我们可以直接遍历原列表,在遍历过程中逐块计算最小值和最大值,完全避免创建子列表的内存开销。
方案1:基于随机访问列表的高效循环(适合ArrayList等)
如果你的idList是支持随机访问的列表(比如ArrayList),可以直接通过索引遍历,计算每个分区的极值:
int gridSize = 6; List<Long> idList = findAllIds(); int totalCount = idList.size(); int partitionSize = (totalCount + gridSize - 1) / gridSize; // 保持和原代码一致的分区大小计算 int currentIndex = 0; while (currentIndex < totalCount) { int partitionEnd = Math.min(currentIndex + partitionSize, totalCount); long currentMin = Long.MAX_VALUE; long currentMax = Long.MIN_VALUE; // 遍历当前分区的元素,统计极值 for (int i = currentIndex; i < partitionEnd; i++) { long id = idList.get(i); if (id < currentMin) currentMin = id; if (id > currentMax) currentMax = id; } // 调用数据库查询 repo.callToDb(currentMin, currentMax); currentIndex = partitionEnd; }
方案2:通用迭代器遍历(适合所有List实现)
如果你的idList是LinkedList这类不支持高效随机访问的列表,改用迭代器遍历可以避免索引访问的性能损耗:
int gridSize = 6; List<Long> idList = findAllIds(); int totalCount = idList.size(); int partitionSize = (totalCount + gridSize - 1) / gridSize; Iterator<Long> iterator = idList.iterator(); int elementCountInPartition = 0; long currentMin = Long.MAX_VALUE; long currentMax = Long.MIN_VALUE; while (iterator.hasNext()) { long id = iterator.next(); currentMin = Math.min(currentMin, id); currentMax = Math.max(currentMax, id); elementCountInPartition++; // 达到分区大小或遍历到末尾时,执行数据库调用并重置统计值 if (elementCountInPartition == partitionSize || !iterator.hasNext()) { repo.callToDb(currentMin, currentMax); elementCountInPartition = 0; currentMin = Long.MAX_VALUE; currentMax = Long.MIN_VALUE; } }
优化说明
- 内存开销:仅维护当前分区的
currentMin、currentMax和几个计数变量,完全避免了子列表的创建,额外内存消耗可以忽略不计。 - 时间效率:遍历一次原列表即可完成所有统计,时间复杂度为O(n),和原方案持平,但减少了子列表对象的创建开销。
- 兼容性:方案2适配所有List实现,无需考虑列表的底层结构。
内容的提问来源于stack exchange,提问作者Vamsi
相关产品推荐
相关产品推荐

