按条件将accgy指定区间拆分为以maxPerRange行索引为边界的子ArrayList
问题分析
你的现有代码存在3个核心逻辑错误:
- 每次命中拆分边界时都直接截取当前索引到区间末尾的片段,会生成大量重复的子列表,完全不符合「相邻拆分点之间取区间」的需求
- 双层循环遍历匹配
rowIndex效率极低,maxPerRange每有1个元素就要多遍历一次全区间 - 没有记录上一次拆分的起始位置,根本无法实现相邻区间的拆分
解决方案
优化思路
- 先把
maxPerRange中所有的rowIndex存入HashSet,把匹配操作的时间复杂度从O(n)降到O(1) - 初始化变量记录上一个拆分点的起始索引,初始值就是你指定的区间起点1590
- 遍历指定区间内的所有元素,命中拆分边界时就截取「上一个起始索引到当前索引」的区间存入结果集,同时更新起始索引为当前索引
- 遍历结束后把最后一段剩余的区间也加入结果集
- 要是需要独立的子列表而不是原列表的视图,就用
new ArrayList<>()把subList的结果包一层
修正后代码
import java.util.HashSet; import java.util.ArrayList; import java.util.List; import java.util.Set; // 先把maxPerRange的rowIndex提取到Set中 Set<Integer> splitRowIndexes = new HashSet<>(); for (int j = 0; j < maxPerRange.size(); j++) { splitRowIndexes.add(maxPerRange.get(j).getRowIndex()); } List<List<Accgy>> partitions1 = new ArrayList<>(); int start = 1590; int end = accgy.size() - 700; for (int i = start; i < end; i++) { int currentRow = accgy.get(i).getCellx().getRowIndex(); if (splitRowIndexes.contains(currentRow)) { // 需要独立子列表就改成 partitions1.add(new ArrayList<>(accgy.subList(start, i))); partitions1.add(accgy.subList(start, i)); start = i; } } // 补上最后一段剩余的区间 if (start < end) { partitions1.add(accgy.subList(start, end)); } // 遍历输出的逻辑不变 for (List<Accgy> c : partitions1) { for (Accgy g : c) { System.out.println(g.getCellx().getNumericCellValue()); System.out.println(g.getCellx().getRowIndex()); } }
注意事项
ArrayList的subList方法返回的是原列表的视图,对原列表的修改会同步到所有子列表,反之亦然。如果后续需要对拆分后的子列表做修改操作,建议在添加时用new ArrayList<>(subList结果)生成独立的新列表。
内容的提问来源于stack exchange,提问作者user15841461
相关产品推荐
相关产品推荐

