C#中 使用yield return 优化大数组或集合的访问
概要
我们在开发过程中,经常需要在一个很大的数组或集合中搜索元素,以满足业务需求。
本文主要介绍通过使用yield return的方式,避免将大量数据全部加载进入内存,再进行处理。从而提高程序的性能。
设计和实现
基本业务场景,我们需要在10000台ATM的数据中找前100台品牌是BrandA的ATM机的数据。
我们不再使用传统的方式,将10000台ATM机的数据全部载入内容,再进行过滤查找。
我们通过yield return方式,只返回一个迭代器,代码如下:
本例中,存在BrandA和BrandB两个品牌,在生成ATM的L集合序列时候,每次都是随机生成ATM机的品牌。
public IEnumerable<ATM> getATMListYield(){List<ATM> atms = new List<ATM>();int count = 0;for(var i=0; i< 10000; ++i){yield return new ATM (){Id = i,Name = "Atm" + i,Brand = getBrand()} ;}yield break;
}
private string getBrand(){Random rd = new Random();int count = rd.Next(100);if (count >= 50) return "BrandA";return "BrandB";
}
调用getATMListYield,进行过滤,找到前100个BrandA的ATM机。完整代码,请参考附录。
public void runGetList(){DataProvider dp = new DataProvider();var lists = dp.getATMList();var count = 0;foreach(var atm in lists){if(atm.Brand == "BrandA") {Console.WriteLine(atm.Name );++ count;}if (count == 100){break;}}}
在foreach循环中,每次访问ATM的集合,只将集合中的一个元素载入内存,进行过滤和比较,当找到100个BrandA的元素,程序停止,不再载入ATM数组的其它元素。
载入全部ATM数据,再进行过滤的代码请见附录。
我们使用Benchmark对两种实现的性能进行测试,测试结果如下:
从测试结果中,可以看出,使用yield return方式,运行时间几乎减少了一半。
由于不需要将全部ATM数据载入内容,yield return方式的内存使用量,仅仅相当于传统方法的2%左右。
附录
Programs.cs
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Net.Mail;
using System.ComponentModel.Design.Serialization;
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Collections.Generic;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
namespace IQueryableIEnumerable
{[MemoryDiagnoser]public class Programs{[Benchmark]public void runGetList(){DataProvider dp =new DataProvider();var lists = dp.getATMList();var count = 0;foreach(var atm in lists){if(atm.Brand == "BrandA") {Console.WriteLine(atm.Name );++ count;}if (count == 100){break;}}}[Benchmark]public void runGetListByYield(){DataProvider dp =new DataProvider();var lists = dp.getATMListYield();int count = 0;foreach(var atm in lists){if(atm.Brand == "BrandA") {Console.WriteLine(atm.Name );++ count;}if (count == 100){break;}}}public static void Main(string[] args){var summary = BenchmarkRunner.Run<Programs>(); }}
}
DataProvider.cs
using System;
using System.Linq;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;namespace IQueryableIEnumerable
{public class DataProvider {public IEnumerable<ATM> getATMList(){List<ATM> atms = new List<ATM>();for(var i=0; i< 10000; ++i){atms.Add(new ATM (){Id = i,Name = "Atm" + i,Brand = getBrand()});}return atms;}public IEnumerable<ATM> getATMListYield(){List<ATM> atms = new List<ATM>();int count = 0;for(var i=0; i< 10000; ++i){yield return new ATM (){Id = i,Name = "Atm" + i,Brand = getBrand()} ;}yield break;}private string getBrand(){Random rd = new Random();int count = rd.Next(100);if (count >= 50) return "BrandA";return "BrandB";}}
}
ATM.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace IQueryableIEnumerable
{public class ATM {public int Id { get; set; }public string Name { get; set; }public string Brand {get;set;} }
}
相关文章:

C#中 使用yield return 优化大数组或集合的访问
概要 我们在开发过程中,经常需要在一个很大的数组或集合中搜索元素,以满足业务需求。 本文主要介绍通过使用yield return的方式,避免将大量数据全部加载进入内存,再进行处理。从而提高程序的性能。 设计和实现 基本业务场景&a…...

ROS实现导航中止(pub命令版+C++代码版)
pub命令 rostopic pub /move_base/cancel actionlib_msgs/GoalID -- {}C代码: stop_navigation.cpp #include <ros/ros.h> #include <geometry_msgs/Twist.h> #include <nav_msgs/Odometry.h> #include <sys/time.h> #include <unistd…...

【VTK】读取一个 STL 文件,并使用 Qt 显示出来,在 Windows 上使用 Visual Studio 配合 Qt 构建 VTK
知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 文章目录 A.hA.cppRef. 直接先把效果放出来,有需要就往下看。 A.h // A.h #pragma once#include <QtWidgets/QMainWindow> #include "…...

数据结构--基础知识
数据结构是什么? 数据结构是计算机科学中研究数据组织、存储和管理的方法和原则。它涉及存储和操作数据的方式,以便能够高效地使用和访问数据。 相关内容 基本组成 数组(Array):数组是一种线性数据结构,…...

天工开物 #7 Rust 与 Java 程序的异步接口互操作
许多语言的高性能程序库都是建立在 C/C 的核心实现上的。 例如,著名 Python 科学计算库 Pandas 和 Numpy 的核心是 C 实现的,RocksDB 的 Java 接口是对底层 C 接口的封装。 Rust 语言的基本目标之一就是替代 C 在这些领域的位置,为开发者提供…...

python实现视频转GIF动图(无水印,包含代码详解和.exe执行文件)
该代码提供了一个简单的界面,允许用户将视频转换为GIF动画,并且可以自定义采样率、GIF帧率和输出大小。修改后的代码将视频帧的大小调整为固定的尺寸,并在生成GIF动画时保持这个尺寸。 一、核心代码实现 核心代码如下: import c…...

一套AI+医疗模式的医院智慧导诊系统源码:springboot+redis+mybatis plus+mysql
一套AI医疗模式的医院智慧导诊系统源码 相关技术: 技术架构:springbootredismybatis plusmysqlRocketMQ 开发语言:java 开发工具:IDEA 前端框架:Uniapp 后端框架:springboot 数 据 库:mys…...

Android 使用modbus协议与可能遇到的问题解决一览
目录 前言一、导入模块二、协议相关1. CRC162. ByteUtil3. ModbusError4. ModbusErrorType5. ModbusFunction6. ModbusRtuMaster7. ByteArrayWriter8. ModbusRtuSerialPortUtil9. ModbusRtuMasterHelp 三、使用总结 前言 本篇文章主要演示android的串口通讯功能,其…...

Virtualbox虚拟机中Ubuntu忘记密码
1、首先重新启动Ubuntu系统,鼠标快速点一下Virtualbox虚拟机窗口获取焦点,然后按住shift键,以调出grub启动菜单。 2、根据提示按下键盘E键进入编辑模式,向下移动光标,将如下"ro quiet splash $vt_handoff"部…...

isPresent()
isPresent() 是 Optional 类的一个方法,用于检查 Optional 对象中是否存在非空值。 Optional 是 Java 8 引入的一个类,用于解决空指针异常的问题。它可以将一个可能为空的值封装成一个对象,并提供了一系列方法来进行安全的操作。 具体来说&…...

DC.js教程_编程入门自学教程_菜鸟教程-免费教程分享
教程简介 DC.js 是一个优秀的 JavaScript 库,用于在浏览器、移动设备中进行数据分析,最终有助于创建数据可视化;DC.js 是一个用于探索大型多维数据集的图表库,它依靠 D3.js 引擎以 CSS 友好的 SVG 格式呈现图表。它允许呈现复杂的…...

Qt应用开发(基础篇)——滑块类 Slider、ScrollBar、Dial
一、前言 滑块类QScrollBar、QSlider和QDial继承于QAbstractSlider,父类主要拥有最大值、最小值、步长、当前值、滑块坐标等信息,滑动的时候触发包含值数据变化、滑块按下、滑块释放等信号。键盘包括左/上和右/下箭头键通过定义的singleStep改变当前值&a…...

iOS的NSUserActivity
NSUserActivity 是 iOS 平台上的一个类,用于支持应用程序之间的交互和继续活动(Continuity)。它主要用于实现 Handoff 功能,使用户可以在不同的 Apple 设备上无缝地继续进行某个任务。NSUserActivity 还可以用于保存和传递应用程序…...

Android HTTP使用(详细版)
前言 在面试过程中,HTTP 被提问的概率还是比较高的。 小林我搜集了 5 大类 HTTP 面试常问的题目,同时这 5 大类题跟 HTTP 的发展和演变关联性是比较大的,通过问答 + 图解的形式由浅入深的方式帮助大家进一步的学习和理解 HTTP 协议。 HTTP 基本概念 Get 与 Post HTTP 特性…...

【雕爷学编程】MicroPython动手做(25)——语音合成与语音识别
知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…...

前端开发:基于cypress的自动化实践
如何在vue中使用cypress如何运行cypress如何编写测试用例如何解决测试数据的问题遇到的元素定位的问题如何看待cypresscypress是否为最佳工具测试怎么办? 如何在vue中使用cypress vue提供了vue-cli 可以快速的创建vue项目。 vue create hello-world在选择安装项里…...

C++类和对象(下部曲)
构造函数 1 构造函数体赋值 在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值 虽然对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化 构造函数体中的语句只能将其称为赋初值,而…...

解决eclipse 打开报错 An error has occurred. See the log file null.
解决eclipse 打开报错an error has ocurred. See the log file null 出现原因:安装了高版本的jdk,更换 jdk 版本,版本太高了。 解决方案:更改环境变量 改成 jkd 1.8...

javascript学习
一、数据类型 所有的变量都以var定义 数值 js不区分小数和整数 文本图形音频视频数组 var id_arr [1,2,3,4,5]对象 // 定义对象 var person {name: zhangsan,age: 3,tags: [java,js,php]} // 取对象的值 var person_name person.name...

基于SSM实现个人随笔分享平台:创作心灵,分享自我
项目简介 本文将对项目的功能及部分细节的实现进行介绍。个人随笔分享平台基于 SpringBoot SpringMVC MyBatis 实现。实现了用户的注册与登录、随笔主页、文章查询、个人随笔展示、个人随笔查询、写随笔、草稿箱、随笔修改、随笔删除、访问量及阅读量统计等功能。该项目登录模…...

从零开始学Docker(二):启动第一个Docker容器
宿主机环境:RockyLinux 9 这个章节不小心搞成命令学习了,后面在整理成原理吧 Docker生命周期 拉取并启动Nginx容器 # 查找镜像 例如:nginx [root192 ~]# docker search nginx 我们可以看到,第一个时官方认证构建的nginx # 拉…...

unity 鼠标事件
Input.GetMouseButtonDown(0)点击屏幕Input.mousePosition鼠标的坐标Input.GetKeyDown(KeyCode.Space)点击空格 1.2D游戏中鼠标触发事件 using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEditor; using Un…...

【ChatGPT】相关解读
ChatGPT 背后的“功臣”——RLHF 技术详解 Meta 发布开源可商用模型 Llama 2,实际体验效果如何? Llama 2线上试用地址:replicate.com/a16z-infr…...

【数据中台】DataX源码进行二开插件
参考官方 使用的离线数据同步工具/平台,实现不同数据库等各种异构数据源之间高效的数据同步功能 工具部署 https://github.com/alibaba/DataX/blob/master/userGuid.md 拉取下来的代码,pom.xml里面注释 <!--<module>tsdbreader</module&g…...

【数据结构与算法】基数排序
基数排序 基数排序(Radix Sort)属于“分配式排序”,又称“桶子法”或 bin sort,顾名思义,它是通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的作用。基数排序法是属于稳定性…...

Java基础一(队列和堆栈)
//示例 //添加新的元素 stack.push(Element e)queue.add(Element e) //满报IllegalStateException异常 queue.offer(Element e) //满成功true,否则false //删除 stack.pop()queue.remove() //移除头部元素,空报异常 queue.poll() //移除头部元素&…...

使用ansible playbook编写lnmp架构
使用ansible playbook编写lnmp架构 - name: nginx playgather_facts: falsehosts: lnmpremote_user: roottasks: - name: stop firewalldservice: namefirewalld statestopped- name: syslinuxcommand: /usr/sbin/setenforce 0ignore_errors: true- name: nginx.repocopy: src/…...

使用 TorchText 进行语言翻译
使用 TorchText 进行语言翻译 本教程说明如何使用torchtext的几个便捷类来预处理包含英语和德语句子的著名数据集的数据,并使用它来训练序列到序列模型,并注意将德语句子翻译成英语 。 它基于 PyTorch 社区成员 Ben Trevett 的本教程,并由 …...

SpringBoot整合SSMP小demo
创建项目 spring web,mybatis,mysql勾选 加入mp和druid,依赖见SpringBoot基础认识_阳光明媚UPUP的博客-CSDN博客 yml数据源 server:port: 81 spring:datasource:druid: #整合方式配置driver-class-name: com.mysql.jdbc.Driverurl: jdbc:m…...

51单片机--红外遥控
文章目录 红外遥控的介绍硬件电路NEC编码外部中断红外遥控实例代码 红外遥控的介绍 红外遥控是一种无线、非接触控制技术,通过使用红外线来传送控制信号。它具有抗干扰能力强、信息传输可靠、功耗低、成本低、易实现等显著优点,因此被广泛应用于各种电子…...