双重for循环优化

项目中有段代码逻辑是个双重for循环,发现数据量大的时候,直接导致数据接口响应超时,这里记录下不断优化的过程,算是抛砖引玉吧~
Talk is cheap,show me your code!

双重for循环优化

    • 1、数据准备
    • 2、原始双重for循环
    • 3、直接使用双重for循环查询条件,增加break条件
    • 4、使用迭代器来删除内层循环中已使用或判断过的元素,减少循环次数
    • 5、把要筛选的信息写成map集合,遍历List时用map.get(key)来实现检索
    • 6、总结

1、数据准备

Order

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Order {private Integer orderId;private String orderName;
}

OrderDetail

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class OrderDetail {private Integer orderDetailId;private Integer orderId;private String orderNums;private String orderAddress;
}

造测试数据

public static List<Order> getOrderTestList() {List<Order> orders = new ArrayList<>();for (int i = 1; i <= 50000; i++) {Order order = new Order();order.setOrderName(UUID.randomUUID().toString());order.setOrderId(i);orders.add(order);}return orders;}public static List<OrderDetail> getOrderDetailTestList() {List<OrderDetail> orderDetails = new ArrayList<>();for (int i = 30000; i >= 1; i--) {OrderDetail orderDetail = new OrderDetail();orderDetail.setOrderAddress(UUID.randomUUID().toString());orderDetail.setOrderId(i);orderDetail.setOrderDetailId(i);orderDetails.add(orderDetail);}return orderDetails;}

2、原始双重for循环

@Testvoid test3() {List<Order> orderTestList = getOrderTestList();List<OrderDetail> orderDetailTestList = getOrderDetailTestList();StopWatch stopWatch = new StopWatch();stopWatch.start();// 直接使用双重for循环查询条件for (Order order : orderTestList) {int orderId = order.getOrderId();for (OrderDetail orderDetail : orderDetailTestList) {if(orderId == orderDetail.getOrderId() ){System.out.println("模拟数据orderAddress 业务处理......" + orderDetail.getOrderAddress());}}}stopWatch.stop();System.out.println("最终耗时" + stopWatch.getTotalTimeMillis());}

执行结果
请添加图片描述

3、直接使用双重for循环查询条件,增加break条件

	@Testvoid test3() {List<Order> orderTestList = getOrderTestList();List<OrderDetail> orderDetailTestList = getOrderDetailTestList();StopWatch stopWatch = new StopWatch();stopWatch.start();// 直接使用双重for循环查询条件,增加break条件for (Order order : orderTestList) {int orderId = order.getOrderId();for (OrderDetail orderDetail : orderDetailTestList) {if(orderId == orderDetail.getOrderId() ){System.out.println("模拟数据orderAddress 业务处理......" + orderDetail.getOrderAddress());break;}}}stopWatch.stop();System.out.println("最终耗时" + stopWatch.getTotalTimeMillis());}

执行结果
请添加图片描述

4、使用迭代器来删除内层循环中已使用或判断过的元素,减少循环次数

	@Testvoid test3() {List<Order> orderTestList = getOrderTestList();List<OrderDetail> orderDetailTestList = getOrderDetailTestList();StopWatch stopWatch = new StopWatch();stopWatch.start();// 使用迭代器来删除内层循环中已使用或判断过的元素,减少循环次数for (Order order : orderTestList) {ListIterator<OrderDetail> orderDetailListIterator = orderDetailTestList.listIterator();int orderId = order.getOrderId();while (orderDetailListIterator.hasNext()) {OrderDetail nextOrderDetail = orderDetailListIterator.next();if(orderId == nextOrderDetail.getOrderId() ){System.out.println("模拟数据orderAddress 业务处理......" + nextOrderDetail.getOrderAddress());orderDetailListIterator.remove();}}}stopWatch.stop();System.out.println("最终耗时" + stopWatch.getTotalTimeMillis());}

执行结果
请添加图片描述

5、把要筛选的信息写成map集合,遍历List时用map.get(key)来实现检索

	@Testvoid test3() {List<Order> orderTestList = getOrderTestList();List<OrderDetail> orderDetailTestList = getOrderDetailTestList();StopWatch stopWatch = new StopWatch();stopWatch.start();//使用stream() 记得一定要判空Map<Integer, String> orderAddressMap =orderDetailTestList.stream().collect(Collectors.toMap(OrderDetail::getOrderId, OrderDetail::getOrderAddress));for (Order order : orderTestList) {int orderId = order.getOrderId();String orderAddress = orderAddressMap.get(orderId);if (StringUtils.hasLength(orderAddress)) {System.out.println("模拟数据orderAddress 业务处理......" + orderAddress);}}if (StringUtils.hasLength(orderAddress)) {System.out.println("模拟数据orderAddress 业务处理......" + orderAddress);}stopWatch.stop();System.out.println("最终耗时" + stopWatch.getTotalTimeMillis());}

测试结果
在这里插入图片描述

6、总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/74270.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Atcoder 做题记录

My OI Blog A R C 155 F \mathbb{ARC \ 155 \ F} ARC 155 F E, F 先咕着&#xff0c;做一些多项式题&#xff0c;这篇题解是我人工翻译的 [1] Double Counting 双重计数 考虑从叶子节点开始&#xff0c;用唯一的方式&#xff08;如果有的话&#xff09;来构造出一棵满足条件的树…

许战海咨询方法论系列白皮书在京隆重发布

新时代&#xff0c;面对剧烈变化的竞争环境&#xff0c;企业如何实现结构性增长&#xff1f; 7月31日&#xff0c;许战海咨询最新研究成果——《主品牌进化战略》、《第二招牌增长战略》、《链主品牌&#xff1a;制造业的竞争之王》三本核心方法论白皮书&#xff0c;重磅发布。…

稍微深度踩坑haystack + whoosh + jieba

说到django的全文检索&#xff0c;网上基本推荐的都是 haystack whoosh jieba 的方案。 由于我的需求对搜索时间敏感度较低&#xff0c;但是要求不能有数据的错漏。 但是没有调试的情况下&#xff0c;搜索质量真的很差&#xff0c;搞得我都想直接用Like搜索数据库算了。 但是…

C++设计模式之过滤器设计模式

C过滤器设计模式 什么是过滤器设计模式 过滤器设计模式是一种行为型设计模式&#xff0c;它允许你在特定的条件下对输入或输出进行过滤&#xff0c;以便实现不同的功能。 该模式有什么优缺点 优点 可扩展性&#xff1a;过滤器设计模式允许您轻松地添加、删除或替换过滤器&a…

CVPR2023新作:源数据集对迁移学习性能的影响以及相应的解决方案

Title: A Data-Based Perspective on Transfer Learning (迁移学习的基于数据的观点) Affiliation: MIT (麻省理工学院) Authors: Saachi Jain, Hadi Salman, Alaa Khaddaj, Eric Wong, Sung Min Park, Aleksander Mądry Keywords: transfer learning, source dataset, dow…

iOS 应用上架的步骤和工具简介

APP开发助手是一款能够辅助iOS APP上架到App Store的工具&#xff0c;它解决了iOS APP上架流程繁琐且耗时的问题&#xff0c;帮助跨平台APP开发者顺利将应用上架到苹果应用商店。最重要的是&#xff0c;即使没有配置Mac苹果机&#xff0c;也可以使用该工具完成一系列操作&#…

算法39:Excel 表列序号

一、需求 给你一个字符串 columnTitle &#xff0c;表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。 例如&#xff1a; A -> 1 B -> 2 C -> 3 … Z -> 26 AA -> 27 AB -> 28 … 示例 1&#xff1a; 输入: columnTitle “A” 输出: 1 示例 2&…

Minio在windows环境配置https访问

minio启动后&#xff0c;默认访问方式为http&#xff0c;但是有的时候我们的访问场景必须是https&#xff0c;浏览器有的会默认以https进行访问&#xff0c;这个时候就需要我们进行配置上的调整&#xff0c;将minio从http访问升级到https。而查看minio的官方文档&#xff0c;并…

配置IPv6 over IPv4手动隧道示例

组网需求 如图1所示&#xff0c;两台IPv6主机分别通过SwitchA和SwitchC与IPv4骨干网络连接&#xff0c;客户希望两台IPv6主机能通过IPv4骨干网互通。 图1 配置IPv6 over IPv4手动隧道组网图 配置思路 配置IPv6 over IPv4手动隧道的思路如下&#xff1a; 配置IPv4网络。配置接…

谁是全球最小ARM MCU?

先是从百度上查找的&#xff0c;找了半天&#xff0c;也找到了一部分。 大小基本在一二毫米左右&#xff0c;外设有多有少&#xff0c;但是好多都买不到货。 而且有些特别小众&#xff0c;开发环境压根没接触过。 然后去外面找了一下&#xff0c;竟然有好几个提到了HC32L110&am…

vue3和typescript_组件

1 components下新建myComponent.vue 2 页面中引入组件&#xff0c;传入值&#xff0c;并且绑定事件函数。 3

java+springboot+mysql企业邮件管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的企业邮件管理系统&#xff0c;系统包含超级管理员、管理员、员工角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;员工管理&#xff1b;反馈管理&#xff1b;系统公告&#xff1b;个人…

使用Git在GitHub上部署静态页面

在GitHub中&#xff0c;我们可以将自己的静态页面部署到GitHub中&#xff0c;它会给我们提供一个地址使得我们的页面变成一个真正的网站&#xff0c;可以供用户访问。 一、在GitHub下创建仓库 二、将项目部署到GitHub上 1. 初始化Git仓库 2. 提交代码 3. 关联远程仓库 在Gi…

PostgreSql 锁

一、概述 在 PostgreSQL 事务中提到&#xff0c;多个用户访问相同数据时可能出现脏读&#xff0c;不可重复度&#xff0c;幻读&#xff0c;更新丢失的问题&#xff0c;为解决这些问题&#xff0c;定义了不同的隔离级别&#xff0c;而隔离级别的具体实现&#xff0c;依靠的就是数…

开放自动化软件的硬件平台

自动化行业的产品主要以嵌入式系统为主&#xff0c;历来对产品硬件的可靠性和性能都提出很高的要求。最典型的产品要数PLC。PLC 要求满足体积小&#xff0c;实时性&#xff0c;可靠性&#xff0c;可扩展性强&#xff0c;环境要求高等特点。它们通常采用工业级高性能嵌入式SoC 实…

Django Rest_Framework(一)

1. Web应用模式 在开发Web应用中&#xff0c;有两种应用模式&#xff1a; 前后端不分离[客户端看到的内容和所有界面效果都是由服务端提供出来的。] 前后端分离【把前端的界面效果(html&#xff0c;css&#xff0c;js分离到另一个服务端或另一个目录下&#xff0c;python服务…

使用 github 同步谷歌浏览器书签

想必使用谷歌浏览器Chrome的用户一定非常头疼的一件事就是&#xff1a;账户不能登录&#xff0c;书签收藏夹不能同步&#xff0c;换一台电脑书签收藏夹没有了&#xff01; 下面教大家一招亲测有效适用的方法解决书签同步问题&#xff0c;在任何电脑都可以同步了 1、去下载谷歌…

从零开始学Docker(三):DockerFile镜像定制

宿主机环境&#xff1a;RockyLinux 9 前言&#xff0c;定制docker镜像的方式有两种&#xff1a; 手动修改容器内容&#xff0c;然后docker commit提交容器为新的镜像通过在dockerfile中定义一系列的命令和参数构成的脚本&#xff0c;然后这些命令应用于基础镜像&#xff0c;依…

websocket服务端大报文发送连接自动断开分析

概述 当前springboot版本&#xff1a;2.7.4 使用依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>现象概述&#xff1a; 客户端和服务端已经有心跳…

iframe跨域解决方案

在 Web 开发中&#xff0c;跨域是指在一个域&#xff08;例如&#xff0c;https://www.example.com&#xff09;的页面中请求了另一个域&#xff08;例如&#xff0c;https://api.example.com&#xff09;的资源&#xff0c;浏览器出于安全考虑会阻止这样的请求。为了解决 ifra…