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

问题描述

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

数组拆分说明:

假设数组: {{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. 注意细节,有时候不起眼的地方就是最危险的地方。
相关推荐
Oneslide3 小时前
Ubuntu 26.04 完整安装 Fcitx5 中文拼音输入法指南(适配默认Wayland)
后端
huangdong_3 小时前
电商平台图片URL原图转换技术深度解析:从缩略图到高清原图的完整方案
java·后端·spring
記億揺晃着的那天3 小时前
Java 调用外部 Go 程序的实践:ProcessBuilder 在生产环境中的应用
java·golang·processbuilder
掘金码甲哥4 小时前
3min手搓一个帮助文档站,很合理吧!
后端
JAVA面经实录9174 小时前
Java 数据结构与算法 (终极完整学习文档)
java·数据结构·算法
JAVA面经实录9174 小时前
操作系统面试题
java·服务器·数据库·计算机网络·面试
一杯奶茶¥5 小时前
基于springboot的失物招领管理系统带万字文档 校园失物招领管理系统 失物认领管理系统java springboot vue
java·vue.js·spring boot·java项目
不能只会打代码5 小时前
边缘视频分析平台的架构设计与性能优化——从750ms到190ms的调优之路
java·spring boot·redis·性能优化·边缘计算·物联网竞赛
小刘|5 小时前
Spring AI Alibaba 集成和风天气 API 实战
java·服务器·前端
KANGBboy5 小时前
java知识五(继承)
java·开发语言