集合拆分不注意写法性能差距真的很大

问题描述

场景:解析数据包中的数据长度,按照完整的数据包进行分组执行(子包不能被拆分)。

数组拆分说明:

假设数组: {{1, 2, 3, ,4 ,5 ,6, 7, 8}, {1, 2, 3, 4}, {1, 2}} 按照给定的 limit 拆分成为多个二维数组

示例1: 如果传入2分为 3 个数组

{{1, 2, 3, ,4 ,5 ,6, 7, 8}}

{{1, 2, 3, 4}}

{{1, 2,}}

示例2: 如果传入6分为 2 个数组

{{1, 2, 3, ,4 ,5 ,6, 7, 8}}

{{1, 2, 3, 4}, {1, 2,}}

示例3:如果传入1分为 2 个数组

{{1, 2, 3, ,4 ,5 ,6, 7, 8}}

{{1, 2, 3, 4}}

{{1, 2}}

说明:一般数据长度在 5000 左右

第一版代码

第一版本代码,其实是最容易想到的,咱们就顺着遍历,然后每次往最后一个集合里面放,比较复杂的就是边界处理, 大致逻辑如下:

  1. 对 resultList0 赋初始值;
  2. currSize 记录当前累计的数量;
  3. 当前的数据放入 resultList 的最后一个子元素中;
  4. 获取下一个元素的长度;
  5. 判断是否达到阈值,达到阈值就创建新的集合中,此处需要注意是否越界。
java 复制代码
private List<List<List<Integer>>> partition(List<List<Integer>> dataList, int limit) {
    List<List<List<Integer>>> resultList = new ArrayList<>();
    int currSize = 0;
    resultList.add(new ArrayList<>());
    for (int i = 0; i < size; i++) {
        resultList.get(dataList.size() - 1).add(dataList.get(i));
        currSize += subResultList.size();
        int nextSize = (i >= dataList.size() - 1) ? 0 : dataList.get(i + 1).size();
        if (currSize + nextSize >= limit && i < size - 1) {
            resultList.add(new ArrayList<>());
            currSize=0;
        }
    }
    return resultList;
}

优化后版本

这个版本就优化了很多,简化了边界处理,以及 get 集合的操作大致逻辑如下:

  1. 如果是 currTotal = 0,就添加一个空集合 resultList 的最后一个元素,并且复位 currTotal = currSize
  2. 在后续循环中,如果 currTotal + currSize > limit 也同样处理
  3. 其他情况 currTotal += currSize
  4. 最后将当前集合添加到 resultList的最后一个元素中
java 复制代码
private List<List<Integer>> partition(List<List<Integer>> dataList, int limit) {
    LinkedList<List<List<Integer>>> resultList = new LinkedList<>();
    int currTotal = 0;
    for (List<Integer> subList : dataList) {
        int currSize = subList.size();
        if (currTotal == 0 || currTotal + currSize > limit) {
            currTotal = currSize;
            resultList.add(new LinkedList<>());
        } else {
            currTotal += currSize;
        }
        resultList.getLast().add(subList);
    }
    return resultList;
}

优化总结

  1. 数据结构上使用, 使用 ArrayList 会拓容,会存在性能开销,LinkedList 底层是链表结构。
  2. 结构上简化,第一种使用探测的方式,需要提前访问下个节点的数据,访问次数 2*n, 第二种只需要访问 n 次,性能提升一倍。
  3. 注意细节,有时候不起眼的地方就是最危险的地方。
相关推荐
帅次12 小时前
Android 17 开发者实战:核心更新与应用场景落地指南
android·java·ios·android studio·iphone·android jetpack·webview
IT_陈寒12 小时前
Vite热更新失灵?你可能漏了这个配置
前端·人工智能·后端
Ramble_Naylor12 小时前
东方通(TongWeb)SpringBoot开发指导
java·spring boot
大鹏说大话12 小时前
SQL 排序与分组实战:解决“分组后取最新数据“
android·java·数据库
uzong12 小时前
面试官:如何做好架构设计
后端·架构
云烟成雨TD12 小时前
Spring AI Alibaba 1.x 系列【64】 ReactAgent 长期记忆
java·人工智能·spring
quan263113 小时前
20260529,日常开发-数据库主从问题
java·mysql·主从·延迟
Cosolar13 小时前
QwenPaw Agent 实现原理深度剖析
后端·面试·架构
JacksonMx13 小时前
@Transactional 最佳实践
java·spring boot·spring·性能优化
Sincerelyplz13 小时前
【AI会议纪要实践】mapReduce、RAG 与结构化输出
java·后端·agent