【性能优化】两种方案优化双层for循环语句 附代码和实例

异步循环和双层嵌套循环(性能优化nodejs从2.8m到28s) 两步优化: 定位问题:该接口使用多次sql查询,并采用了async,另外在数据的处理中使用了map,forEach嵌套。 方案: 1/使用了bluebird来异步并发请求,替代原来的async请求。 2/数据处理确实无法减少嵌套,我采用了for循环来替代map,forEach,虽然降低了代码的可读性,但是这里因为数据量比较大,两层循环的原因,确实能有效节约时间。 优化前: 优化后: ... 阅读详情

现有如下需求,需在订单信息类中根据用户信息类的userId匹配到对应的信息并输出商品skuId。

先给出实体类:用户信息类UserInfo和订单信息类OrderInfo。用户信息类如下所示:

/**
 * @author Carson Chu
 * @date 2020/1/13 19:43
 * 用户信息类
 */
@Data
public class UserInfo {
    /* 用户Id */
    private String userId;

    /* 用户名 */
    private String name;

    /* 用户性别 */
    private String gender;

    public UserInfo(String userId, String name, String gender) {
        this.userId = userId;
        this.name = name;
        this.gender = gender;
    }
}

订单信息类如下:

/**
 * @author Carson Chu
 * @date 2020/1/13 19:44
 * 订单信息类
 */
@Data
public class OrderInfo {
    /* 用户Id */
    private String userId;

    /* 订单号 */
    private Long orderId;

    /* 商品sku */
    private Long skuId;

    /* 商品价格 */
    private BigDecimal price;

    public OrderInfo(String userId, Long orderId, Long skuId, BigDecimal price) {
        this.userId = userId;
        this.orderId = orderId;
        this.skuId = skuId;
        this.price = price;
    }
}

假设用户信息表和订单信息表中各有十万条数据,需要匹配到商品skuId,先采用双层for循环,附上main()方法逻辑:

/**
 * @author Carson Chu
 * @date 2020/1/13 20:09
 */
public class Main {
    public static void main(String[] args) {
        /* 用户信息集合 */
        List<UserInfo> userInfoList = Lists.newArrayList();
        /* 订单信息集合 */
        List<OrderInfo> orderInfoList = Lists.newArrayList();
        /* 手动向集合中添加十万条数据 */
         for (int i = 0; i < 100000; i++) {
            String userId = i + "";
            String name = "用户" + i;
            String gender = "female";
            UserInfo userInfo = new UserInfo(userId, name, gender);
            Long orderId = Long.valueOf(createNum(6));
            Long skuId = Long.valueOf(createNum(8));
            OrderInfo orderInfo = new OrderInfo(userId, orderId, skuId, new BigDecimal("66"));
            userInfoList.add(userInfo);
            orderInfoList.add(orderInfo);
        }       
         
        long start = System.currentTimeMillis();
        for (UserInfo userInfo : userInfoList) {
            for (OrderInfo orderInfo : orderInfoList) {
                if (userInfo.getUserId().equals(orderInfo.getUserId())) {
                    System.out.println(orderInfo.getSkuId());
                }
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("采用原始的双层for循环查询累计耗时:" + (end - start) + "毫秒");
    }
    
    /**
     * 生成指定长度的随机数
     *
     * @param length
     * @return
     */
    public static String createNum(int length) {
        StringBuilder sb = new StringBuilder();
        Random rand = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(rand.nextInt(10));
        }
        return sb.toString();
    }
}

采用双层for循环的运行时间很长,将近4分钟,如下图所示:
在这里插入图片描述
如上图所示,查询消耗十分巨大,这种响应时间,玩笑开大了!这还不包括复杂业务场景下的I/O消耗等,可以说性能极其糟糕,线上环境绝对不允许如此缓慢的响应时间。双层for循环时间复杂度O(N2),效率极低,并且性能随着处理容量N呈急剧下降(开发中应该保证性能平缓下降)甚至将导致接口直接崩溃。那么,应该如何优化呢?

方案一:HashMap

将main()方法中的主要处理逻辑修改为采用哈希,使用两次单层循环:

 		long start = System.currentTimeMillis();
        Map<String, Long> hashMap = new HashMap<>();
         /* 先将所有的订单信息都放在HashMap,哈希的查找时间复杂度是O(1) */
        for (OrderInfo orderInfo : orderInfoList) {
            hashMap.put(orderInfo.getUserId(), orderInfo.getSkuId());
        }
        for (UserInfo userInfo : userInfoList) {
            System.out.println(hashMap.get(userInfo.getUserId()));
        }
        long end = System.currentTimeMillis();
        System.out.println("利用HashMap查询累计耗时:" + (end - start) + "毫秒");

在这里插入图片描述
如上图所示,哈希的查询十分的快,响应时间缩小到了915毫秒,为秒级,效率比双层for循环提高了两百多倍。

方案二:JDK8的lambda表达式和stream流

此外也可以采用jdk8的lambda表达式:

long start = System.currentTimeMillis();
        // 将List转为Map,这里key一定要为唯一值
        Map<String, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(userInfo -> userInfo.getUserId(), userInfo -> userInfo));
        // 商品skuId集合
        List<Long> skuIdList = Lists.newArrayList();
        skuIdList = orderInfoList.stream().map(orderInfo -> {
            return getSkuId(userInfoMap.get(orderInfo.getUserId()), orderInfo);
        }).collect(Collectors.toList());
        skuIdList.stream().forEach(skuId -> {
            System.out.println("商品skuId:" + skuId);
        });
        long end = System.currentTimeMillis();
        System.out.println("利用lambda表达式和stream流查询累计耗时:" + (end - start) + "毫秒");

附加匹配用户信息和订单信息的方法逻辑:

/**
     * 匹配用户信息和订单信息,成功匹配后返回用户对应的商品skuId
     *
     * @param userInfo
     * @param orderInfo
     * @return
     */
    private static Long getSkuId(UserInfo userInfo, OrderInfo orderInfo) {
        if (orderInfo.getUserId().equals(userInfo.getUserId())) {
            return orderInfo.getSkuId();
        }
        return null;
    }

在这里插入图片描述
如上图所示,耗时也是毫秒级的,和哈希效率相当,因为事实上这种stream流就是基于HashMap的。双层for循环和这两种方案相比,执行效率和用户体验上可谓是天差地别。

Java for循环嵌套for循环,你需要懂的代码性能优化技巧 Java for循环嵌套for循环 性能优化 阅读详情

相关推荐

【Anaconda】解决“libGL error: MESA-LOADER: failed to open iris”问题

stackoverflow中的“libGL error: MESA-LOADER: failed to open iris”问题。而在自己创建的conda环境中的lib下出现`GLIBCXX_3.4.30’ not found 的情况。在上述解决方案中,将第一行命令的lib路径换成自己创建的conda环境lib路径,运行指令,问题解决。目前问题解决,总结一下查找资料以及解决方法。运行如下命令,发现本地支持。

quintus0505的博客 5024

双重循环优化,提高运行效率

循环次数较少的时候for循环一般不会影响运行效率,但一旦循环次数较多,成千上万的时候,循环次数越多,效率就越慢,最近在做一程序的时候要解决优化问题,反复查看只有优化双重for循环才能提高效率。事实证明,优化后效率提升了一大半。  当然,本文也有借鉴其他博友的方法,根据以下方法提升效率: 1、实例化变量放在for循环外,减少实例化的次数 2、把能在循环外计算的,尽量在循环外计算,减少在内层的运算...

qq_38378235的博客 1万+

Unity游戏接入穿山甲广告SDK全攻略:从零到上线的避坑指南

本文为Unity开发者提供了接入穿山甲广告SDK的完整实战指南。详细解析了从账号注册、应用创建到Unity插件集成、安卓与iOS平台打包配置的全流程,并重点分享了广告加载失败、展示异常等常见问题的排查与解决方案,帮助开发者高效实现游戏广告变现。

weixin_29015899的博客 536

一天一个小技巧-优化双重for循环

你还在用双层for循环吗?太慢了

weixin_43747703的博客 6470

【教程4>第10章>第13节】基于FPGA的图像双边滤波开发——单通道双边滤波Verilog实现

本文介绍了基于Vivado 2022.2的单通道高斯滤波FPGA实现方案。主要内容包括:1)采用3×3窗口像素提取、高斯权值计算、exp指数运算等模块构建双边滤波系统;2)详细分析了Verilog HDL实现的顶层设计文件,包含窗口数据生成、指数计算、混合权重、归一化处理等关键模块;3)展示了图像双边滤波器的RTL结构图。该设计为后续实现RGB三通道图像高斯滤波及MATLAB联合仿真奠定了基础。

FPGA/MATLAB学习教程/源码/项目合作开发 262

Labview邪修01:贪吃蛇小游戏

摘要:博主使用LabVIEW 2020(32位)复刻了经典贪吃蛇游戏。程序具备随机生成蛇(初始长度3)和食物、三档速度调节、键盘方向控制等功能,碰撞边界或自身即游戏结束。实现过程包括:1)界面设计,使用二维颜色盒数组构建游戏区,添加速度枚举控件和功能按钮;2)程序架构,采用模块化设计包含Main.vi、Start.vi等6个核心VI,分别处理初始化、位置计算、碰撞检测等逻辑;3)事件驱动机制,通过开始/结束事件、按键响应和超时循环实现游戏流程控制。运行时可实时显示分数,完整还原了贪吃蛇的核心玩法。

weixin_38637405的博客 970

双重for循环优化

通过迭代删除或者利用map集合特性均能够有效提升查询效率

jike11231的博客 6102

基于单片机的智能体重秤设计与嵌入式程序实现

智能体重秤的基本功能是测量用户的体重,并将数据通过无线方式传输到终端设备(如智能手机、电脑或云平台)进行管理。体重测量:实时测量用户体重,并进行数据存储。BMI(体质指数)计算:基于体重和身高计算BMI值,帮助用户了解健康状况。多用户管理:通过蓝牙或Wi-Fi技术支持多用户体重数据记录。健康数据分析:结合历史数据分析体重变化趋势。语音播报:通过语音播报用户体重,便于老人或视力不便的人士使用。数据同步:通过App或云平台同步数据,进行长期健康监控。

2201_76125393的博客 1755

两层for循环嵌套如何优化

最近在项目中遇到一个需求,需要将两个数据表的数据进行比对,这涉及到了两层for循环的嵌套。一开始写得时候发现耗时太久,尝试优化一下。优化的总结如下: 1.将for循环内的无关表达式提取到外面。 for(){ for(){ a=a*b*c; } } 应该要将b*c的值先算好,然后再放进循环内。否则会每次循环都浪费资源。 2.将for里面的条件先处理好 相...

leihope_的博客 1万+

一个中科大差生的8年程序员工作总结

今年终于从大菊花厂离职了,离职前收入大概60w不到吧,在某乎属于比较差的,今天终于有空写一下自己的职场故事,也算是给自己近8年的程序员工作做个总结复盘。近8年有些事情做对了,也有更多事情做错了,在这里记录一下,希望能够给后人一些帮助吧,也欢迎私信交流。文笔不好,见谅,有些细节记不清了,如果有出入,就当是我编的这个故事吧。 PS:有几个问题先在这里解释一下,评论就不一一回复了 1、关于差生,我本人在科大时确实成绩偏下,差生主要讲这一点,没其他意思。 2、因为买房是我人生中的大事,我认为需要记录和总结一下

陈小房的自我修炼 5万+

基于FPGA的时间数字转换(TDC)设计(五:基于Carry4的高精度TDC设计)

基于FPGA的时间数字转换(TDC)设计,此为第五篇:基于Carry4的高精度TDC设计。提供工程文件及MATLAB测试分析代码

sdau2005的博客 8803

两个for循环嵌套优化

数量较小时,嵌套for循环运行基本没什么影响,如果数据量较大运行时间明显变长,毕竟复杂度是O(n),数据量大或者循环嵌套过多,代码执行耗时会很恐怖。前段时间在公众号中看到一篇技术文章,关于for循环嵌套的优化方法,感觉很实用(比较原来自己遇到过),下面分享给大家,同时加深理解,欢迎讨论。在for循环中使用break,减少执行次数,从而减少耗时,当然也是针对数据量不大,嵌套少,有一定的判断条件。使用map 去优化,map的取值效率 在多数的情况下是能维持接近 O(1) 的 ,数组加链表。

蜗牛快爬 2587

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

双层for循环,代码性能优化技巧

????这是一个或许对你有用的社群????一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料:《项目实战(视频)》:从书中学,往事中“练”《互联网高频面试题》:面朝简历学习,春暖花开《架构 x 系统设计》:摧枯拉朽,掌控面试高频场景题《精进 Java 学习指南》:系统学习,互联网主流技术栈《必读 Java 源码专栏》:知其然,知其所以然????这是一个或许...

weixin_44421461的博客 1048

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

双层for循环,优化完耗时节省90%

这其实就是时间复杂度,for循环嵌套for循环,就好比 循环每一个 user ,拿出 userId 需要在里面的循环从 userMemo list集合里面 按顺序去开盲盒匹配,拿出第一个,看看userId ,拿出第二个,看看userId ,一直找匹配的。相当于拿到userId 想去开盲盒的时候, 根据userId 这个key hash完能直接找到数组里面的索引标记位, 如果底下没链表(有的话O(logN)),直接取出来就完事了。其实数据量小的话,其实没多大性能差别,不过我们还是需要知道一些技巧点。

m0_73735578的博客 980

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

js优化双层for循环的方法

最近在项目中遇到一个需求,需要将两个数据表的数据进行比对,这涉及到了两层for循环的嵌套。数据少的时候还好,一旦数据多就是成倍的循环次数,性能不好,尝试优化一下。假如两次循环都是1000个元素,那么循环次数是:1000*1000之前的双层for循环写法: 优化后写法 相当于一个for循环就能搞定 优化之后的循环次数:1000...

铁锤妹妹的博客 5346

Vue的v-for双层循环

vue的v-for双层循环 结构嵌套的父子循环 item表示当前的数据,index表示索引 key的作用:帮助Vue区分不同的元素,从而提高性能 in 后面表示遍历的数组 <div id="app"> <ul v-for="(item, index) in list1" :key="index"> <li v-for="(i, d) in item.listitem" :key="d">{{i.name}}</li>

leilei__66的博客 1万+

双重for循环遍历优化

下面展示3中遍历循环方式耗时比较 public static void main(String[] args) { /* 用户信息集合 */ List<UserInfo> userInfoList = new ArrayList<>(); /* 订单信息集合 */ List<OrderInfo> orderInfoList = new ArrayList<>(); /* 手动向集合

qq_41345292的博客 5091

正确编写【双层For循环】提升代码性能

最近和工作了两年多的朋友聊天,发现他竟然不知道如何编写双层For循环才能提升性能。所以特此分享出来,希望对大家有所帮助,这个在工作中非常实用!

程序员四海 581

java8双层for循环,Java8处理List的双层循环问题

Java处理List的双层循环程序员经常遇到,一般都是当两个List某个值满足某条件时候,进行相应的处理;1.list和map之间的相互转换/*** 两个List对象当id相同的时候(注意是两个对象,而非两个集合)* @param husbands* @param wives*/private static void test8(List husbands, List wives) {List f...

weixin_35125597的博客 4042

JAVA树结构的三种组装方式(递归.双层for循环,map)

一.前言 今天工作中做权限分配部分要查询菜单,而菜单是数结构,刚开始我是用的递归,后来又仔细思考了一下,总结了一下. 二.三种组装方法 1. 递归调用 public Result getBmsMenuList(UserSessionVO userSessionInfo) { // 查询顶级节点菜单 List<BmsMenuVO> bmsMenuVOList = bmsMenuDao.selectBmsMenuList(new BmsMenuQueryC

qq_39999478的博客 2381

java for循环map赋值_Java for循环Map集合优化实现解析

这篇文章主要介绍了Java for循环Map集合优化实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下在《for循环实战性能优化》中提出了五种提升for循环性能的优化策略,这次我们在其中嵌套循环优化小循环驱动大循环的基础上,借助Map集合高效的查询性能来优化嵌套for循环。如果小循环和大循环的集合元素数量分别为M和N,则双层For循环的循环次...

weixin_33304896的博客 1772

java map 优化_Java for循环Map集合优化实现解析

这篇文章主要介绍了Java for循环Map集合优化实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下在《for循环实战性能优化》中提出了五种提升for循环性能的优化策略,这次我们在其中嵌套循环优化小循环驱动大循环的基础上,借助Map集合高效的查询性能来优化嵌套for循环。如果小循环和大循环的集合元素数量分别为M和N,则双层For循环的循环次...

weixin_42676678的博客 632

for 循环的效率

1、单层for循环 long start =System.currentTimeMillis(); int sum=0; for(int i=0;i<1000000000;i++) { sum=1+1; } long end = System.currentTimeMillis(); System.out.println(end-start); //输出时间差为...

weixin_30244889的博客 293
上一篇: 【MySQL】一次线上的OR查询导致的索引失效 附解决方案
下一篇: 【Java基础】HashMap底层实现原理 附源码分析及面试题,带你深入Java集合
少侠露飞
博客等级 码龄9年 214粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值