C#中List<T>底层原理剖析
C#中List底层原理剖析
- 1. 基础用法
- 2. List的Capacity与Count:
- 3.List的底层原理
- 3.1. 构造
- 3.2 Add()接口
- 3.3 Remove()接口
- 3.4 Inster()接口
- 3.5 Clear()接口
- 3.6 Contains()接口
- 3.7 ToArray()接口
- 3.8 Find()接口
- 3.8 Sort()接口
- 4. 总结
- 5. 参考
1. 基础用法
list.Max() 取最大元素
list.Avgage() 取平均值
static void Main()
{List<string> names = new List<string>();names.Add("一号元素");names.Add("二号元素");names.Add("狗");names[2] = "三号元素";//修改第三个元素string[] str = new string[] { "四号元素", "五号元素", "六号元素" };names.AddRange(str);//为集合增加数组Console.WriteLine("当前集合元素个数为{0}",names.Count);//返回集合元素个数Console.WriteLine("当前集合的容量为{0}", names.Capacity);//返回当前集合的容量//当添加元素的时候集合的容量不足以容纳所有元素就会自动增加目前元素数一倍的容量。Console.WriteLine(names.Contains("三号元素"));//返回集合中是否存在某元素,bool类型names.IndexOf("三号元素");//返回元素的索引值names.Clear();//清空所有元素,元素个数为0,但是容量不变
}
2. List的Capacity与Count:
- Count 属性表示 List 中实际包含的元素数量。它是一个只读属性。
- Capacity 属性表示 List 内部数组的容量,即它可以容纳的元素的数量。容量是指分配给列表的内部数组的大小,而不是列表中实际包含的元素数量。
- 当添加元素时,如果内部数组的容量不够,List 会自动调整容量以容纳更多的元素。
List<int> list1= new List<int>();
WriteLine($"List的初始容量:{list1.Capacity}");
WriteLine($"List的初始数量:{list1.Count}");
list1.Add(0);
WriteLine($"通过Add()添加一个元素后的容量:{list1.Capacity}");
WriteLine($"通过Add()添加一个元素后的数量:{list1.Count}");
以上代码输出:
List的初始容量:0
List的初始数量:0
通过Add()添加一个元素后的容量:4
通过Add()添加一个元素后的数量:1
3.List的底层原理
3.1. 构造
private class List<T> : Ilist<T>, System.Collections.IList, IReadOnlyList<T>
List内部是由数组实现的,当没有指定额定容量时,初始容量为0。
3.2 Add()接口
将给定对象添加到此列表的末尾。每次增加元素前,都会判断数组容量是否够。不够则进行扩容。
public void Add(T item)
- 每次扩容都会扩充一倍。数组初始值为0,扩容初始值为4,因此整个扩容路线是:0-4-8-16-32-64-125-256……
- 每次扩容都会申请新的空间,然后进行元素拷贝,然后还要回收旧空间。会给GC造成不小的负担。
- 另外还有浪费空间的缺点。比如存放126个元素时,会扩容到256的空间,剩下的130个空间就浪费了。
3.3 Remove()接口
删除列表中首次出现的item。将从头到尾搜索,使用Object.Equal()进行相等的判断。
public bool Remove(T item)
- 找到要删除的位置后,使用Array.Copy()进行覆盖;
- 时间复杂度O(n);
- 删除一个元素后,内部数组的容量不变。
3.4 Inster()接口
功能:在给定索引处插入元素。每次插入元素前都会检查当前容量是否足够,如果不够则进行扩容。
public void Insert(int index, T item);
- 在插入元素时,采用的也是复制数组的形式,将数组指定索引后面的元素向后移动一个位置。
- 与Add()类似,会给GC产生负担,并且存在空间浪费的问题。
3.5 Clear()接口
功能:清除列表内容。注意:只是将Count置,之前申请空间不变,也就是Capacity不变。
List<int> list1= new List<int>();
list1.Add(0);
WriteLine($"通过Add()添加一个元素后的容量:{list1.Capacity}");
WriteLine($"通过Add()添加一个元素后的数量:{list1.Count}");
list1.Clear();
WriteLine($"Clear后的容量:{list1.Capacity}"); //清除后容量不变。即之前申请的空间不变
WriteLine($"Clear后的数量:{list1.Count}"); //数量置0
以上输出:
通过Add()添加一个元素后的容量:4
通过Add()添加一个元素后的数量:1
Clear后的容量:4
Clear后的数量:0
3.6 Contains()接口
功能:确定某元素是否在List中。
public bool Contains(T item)
- 使用线性查找的方式,挨个比较元素。
3.7 ToArray()接口
复制列表到一个新数组,O(n)的操作。
public T[] ToArray()
3.8 Find()接口
功能:查找满足指定条件的元素。接受一个Predicate委托作为参数,该委托定义了要应用于每个元素的条件。
public T Find(Predicate<T> match)
- 线性查找的方式,挨个比较,返回满足条件的第一个元素。
- 用法:
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 }; // 使用Find函数查找大于3的第一个元素 int result = numbers.Find(x => x > 3); //Lambda表达式x => x > 3表示条件 Console.WriteLine(result); // 输出: 4
3.8 Sort()接口
功能:对列表中的元素进行排序。Sort 方法使用元素的默认比较器进行排序,或者可以传递一个自定义的比较器作为参数。
public void Sort(int index, int count, TComparee<T> comparer)
- index与count是指定排序区间。不指定的话则整个列表进行排序;
- 用法
List<int> numbers = new List<int> { 5, 2, 8, 1, 3 }; numbers.Sort(); numbers.Sort((x, y) => y.CompareTo(x));// 使用自定义比较器对列表进行降序排序
- 该方法在原地修改列表,而不是返回排序后的列表。
- 排序时使用Array.Sort()方法进行排序,该方法内部采用了快速排序,效率是O(nlogn).
4. 总结
- List的效率并不高,甚至比数组还差,只是通用性强而已;
- List 的内存分配方式也不合理。当List 里的元素不断增加时,会多次重新分配数组,导致原来的数组被抛弃,造成回收的压力。
- 对于第2点的问题,我们可以在创建List 实例时提前告知 List 对象最多会有多少元素在里面,这样 List 就不会因为空间不够而抛弃原有的数组去重新申请教组了。例如:
List<int> list11 = new List<int>(128); WriteLine($"容量:{list11.Capacity}"); //容量:128 WriteLine($"数量:{list11.Count}"); //数量:0
- List是线程不安全的。
- 当多个线程同时访问和修改同一个 List 实例时,可能会导致不可预测的结果或发生错误。
- 例如,并发读写的问题。一个线程正在读取列表的元素,而另一个线程在同时修改列表,这可能导致读取到无效或不正确的数据。
- 可使用同步机制解决该问题。lock语句或其他同步机制来保护对 List 的并发访问。确保同一时间只有一个线程访问列表。
5. 参考
List源码地址:链接: https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs
相关文章:
C#中List<T>底层原理剖析
C#中List底层原理剖析 1. 基础用法2. List的Capacity与Count:3.List的底层原理3.1. 构造3.2 Add()接口3.3 Remove()接口3.4 Inster()接口3.5 Clear()接口3.6 Contains()接口3.7 ToArray()接口3.8 Find()接口3.8 Sort()接口 4. 总结5. 参考 1. 基础用法 list.Max() …...
Leetcode 3003. Maximize the Number of Partitions After Operations
Leetcode 3003. Maximize the Number of Partitions After Operations 1. 解题思路2. 代码实现 题目链接:10038. Maximize the Number of Partitions After Operations 1. 解题思路 这一题我看实际比赛当中只有72个人做出来,把我吓得够呛,…...
MySQL第一讲:MySQL知识体系详解(P6精通)
MySQL知识体系详解(P6精通) MySQL不论在实践还是面试中,都是频率最高的。本系列主要对MySQL知识体系梳理,将给大家构建JVM核心知识点全局知识体系,本文是MySQL第一讲,MySQL知识体系详解。 文章目录 MySQL知识体系详解(P6精通)1、MySQL学习建议1.1、为什么学习 MySQL?1.2、…...
逻辑回归简单案例分析--鸢尾花数据集
文章目录 1. IRIS数据集介绍2. 具体步骤2.1 手动将数据转化为numpy矩阵2.1.1 从csv文件数据构建Numpy数据2.1.2 模型的搭建与训练2.1.3 分类器评估2.1.4 分类器的分类报告总结2.1.5 用交叉验证(Cross Validation)来验证分类器性能2.1.6 完整代码…...
Python print 高阶玩法
Python print 高阶玩法 当涉及到在Python中使用print函数时,有许多方式可以玩转文本样式、字体和颜色。在此将深入探讨这些主题,并介绍一些print函数的高级用法。 1. 基本的文本样式与颜色设置 使用ANSI转义码 ANSI转义码是一种用于在终端࿰…...
Wpf 使用 Prism 实战开发Day09
设置模块设计 1.效果图 一.系统设置模块,主要有个性化(用于更改主题颜色),系统设置,关于更多,3个功能点。 个性化的颜色内容样式,主要是从 Material Design Themes UI简称md、提供的demo里复制代码过来使用的。 1.设置…...
网络端口(包括TCP端口和UDP端口)的作用、定义、分类,以及在视频监控和流媒体通信中的定义
目 录 一、什么地方会用到网络端口? 二、端口的定义和作用 (一)TCP协议和UDP协议 (二)端口的定义 (三)在TCP/IP体系中,端口(TCP和UDP)的作用 (…...
flink如何写入es
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、写入到Elasticsearch5二、写入到Elasticsearch7总结 前言 Flink sink 流数据写入到es5和es7的简单示例。 一、写入到Elasticsearch5 pom maven依赖 <d…...
Java、Python、C++和C#的界面开发框架和工具的重新介绍
好的,以下是Java、Python、C和C#的界面开发框架和工具的重新介绍: Java界面开发: Swing: 是Java提供的一个基于组件的GUI工具包,可以创建跨平台的图形用户界面。它提供了丰富的组件和布局管理器,使得界面开发相对简单。…...
Java二叉树的遍历以及最大深度问题
Java学习面试指南:https://javaxiaobear.cn 1、树的相关概念 1、树的基本定义 树是我们计算机中非常重要的一种数据结构,同时使用树这种数据结构,可以描述现实生活中的很多事物,例如家谱、单位的组织架构、等等。 树是由n&#…...
Apollo 9.0搭建问题记录
虚拟机安装 可以看这个:https://blog.csdn.net/qq_45138078/article/details/129815408 写的很详细 内存 为了学习 Apollo ,所以只是使用了虚拟机,内存得大一点(128G),第一次,就是因为分配内…...
【心得】PHP文件包含高级利用攻击面个人笔记
目录 一、nginx日志文件包含 二、临时文件包含 三、php的session文件包含 四、pear文件包含 五 、远程文件包含 文件包含 include "/var/www/html/flag.php"; 一 文件名可控 $file$_GET[file]; include $file.".php"; //用php伪协议 ࿰…...
[scala] 列表常见用法
文章目录 不可变列表 List可变列表 ListBuffer 不可变列表 List 在 Scala 中,列表是一种不可变的数据结构,用于存储一系列元素。列表使用 List 类来表示,它提供了许多方法来操作和处理列表。 下面是一些常见的使用列表的示例: 创…...
python 使用urllib3发起post请求,携带json参数
当通过python脚本,发起http post请求,网络上大多是通过fields传递数据,然而这样,服务器收到的请求,但无法解析json数据。类似这些链接: Python urllib3库使用指南 软件测试|Python urllib3库使用指南 p…...
深入理解堆(Heap):一个强大的数据结构
. 个人主页:晓风飞 专栏:数据结构|Linux|C语言 路漫漫其修远兮,吾将上下而求索 文章目录 前言堆的实现基本操作结构体定义初始化堆(HeapInit)销毁堆(HeapDestroy) 重要函数交换函数(…...
抖音在线查权重系统源码,附带查询接口
抖音权重在线查询只需输入抖音主页链接,即可查询作品情况。 搭建教程 上传源码并解压 修改数据库“bygoukai.sql” 修改“config.php” 如需修改水印请修改第40行 如需修改限制次数,请修改第156行 访问域名user.php即可查看访问用户,停…...
Spring Framework和SpringBoot的区别
目录 一、前言 二、什么是Spring 三、什么是Spring Framework 四、什么是SpringBoot 五、使用Spring Framework构建工程 六、使用SpringBoot构建工程 七、总结 一、前言 作为Java程序员,我们都听说过Spring,也都使用过Spring的相关产品࿰…...
2024--Django平台开发-Django知识点(三)
day03 django知识点 项目相关路由相关 urls.py视图相关 views.py模版相关 templates资源相关 static/media 1.项目相关 新项目 开发时,可能遇到使用其他的版本。虚拟环境 老项目 打开项目虚拟环境 1.1 关于新项目 1.系统解释器命令行【学习】 C:/python38- p…...
Github 2024-01-08开源项目周报 Top14
根据Github Trendings的统计,本周(2024-01-08统计)共有14个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目5TypeScript项目3C项目2Dart项目1QML项目1Go项目1Shell项目1Rust项目1JavaScript项目1C#项目1 免费…...
vue3 的内置组件汇总
官方给出的说明: Fragment: Vue 3 组件不再要求有一个唯一的根节点,清除了很多无用的占位 div。Teleport: 允许组件渲染在别的元素内,主要开发弹窗组件的时候特别有用。Suspense: 异步组件,更方便开发有异步请求的组件。 一、fr…...
ARM工控机Node-red使用教程
嵌入式ARM工控机Node-red安装教程 从前车马很慢书信很远,而现在人们不停探索“科技改变生活”。 智能终端的出现改变了我们的生活方式,钡铼技术嵌入式工控机协助您灵活布建能源管理、大楼自动化、工业自动化、电动车充电站等各种多元性IoT应用ÿ…...
Visual Studio 发布程序自动更新 ClickOnce和AutoUpdater测试
文章目录 前言运行环境ClickOnce(Visual Studio 程序发布)IIS新建文件夹C# 控制台测试安装测试更新测试卸载 AutoUpdaterDotNET实现原理简单使用新建一个WPF项目 代码封装自动更新代码封装简单使用 总结 前言 虽然写的大部分都是不联网项目,…...
Codeforces Round 761 (Div. 2) E. Christmas Chocolates(思维题 树的直径 二进制性质 lca)
题目 n(n<2e5)个值,第i个值ai(0<ai<1e9),所有ai两两不同 初始时,选择两个位置x,y(x≠y),代表需要对这两个位置进行操作,要把其中一个值变成另一个 你可以执行若干次操作,每一次,你可…...
知识图谱之汽车实战案例综述与前瞻分析
知识图谱的前置介绍 什么是知识图谱 知识图谱本质(Knowledge Graph)上是一种叫做语义网络(semantic network ) 的知识库,即具有有向图结构的一个知识库;图的结点代表实体(entity)或者概念(con…...
网关Gateway
什么是网关? 网关实质上是一个网络通向其他网络的 IP 地址,是当前微服务项目的"统一入口"。 网关能做什么? 反向代理 、鉴权、 流量控制、 熔断、 日志监控等 图片原文:http://t.csdnimg.cn/SvUJh 核心概念 Router(…...
java 生成一个当前时间的时间搓
开发过程中 用时间搓数值格式存储 会更加精准 那么 我们在一些日常增删查改中就可以用时间搓来记录操作时间 就一行代码 long timestamp System.currentTimeMillis();他就能生成当前时间的时间搓 运行结果如下 然后 我们可以在 http://shijianchuo.wiicha.com/ 上进行转换查…...
金融中IC和IR的定义
当谈到金融领域时,IC(Information Coefficient)和IR(Information Ratio)通常是用来评估投资组合管理绩效的指标。它们都涉及到投资者对信息的利用和管理的效果。 信息系数(IC - Information Coefficient&a…...
Git(2):Git环境的安装
本教程里的git命令例子都是在Git Bash中演示的,会用到一些基本的linux命令,在此为大家提前列举: ls/ll 查看当前目录cat 查看文件内容touch 创建文件vi vi编辑器(使用vi编辑器是为了方便展示效果,学员可以记事本、edi…...
Pytest单元测试系列[v1.0.0][pytest插件常用技巧]
使用pytest-xdist并发执行测试 pytest-xdist:Run Tests in Parallel [https://pypi.python.org/pypi/pytest-xdist] 在自动化测试中有些资源只能同时被一个测试用例访问,如果不需要同时使用同一个资源,那么测试用例便可以并行执行 执行命令…...
嵌入式培训机构四个月实训课程笔记(完整版)-Linux系统编程第五天-Linux消息共享内存练习题(物联技术666)
更多配套资料CSDN地址:点赞+关注,功德无量。更多配套资料,欢迎私信。 物联技术666_嵌入式C语言开发,嵌入式硬件,嵌入式培训笔记-CSDN博客物联技术666擅长嵌入式C语言开发,嵌入式硬件,嵌入式培训笔记,等方面的知识,物联技术666关注机器学习,arm开发,物联网,嵌入式硬件,单片机…...
2_试列出网站开发建设的步骤/网页设计模板素材图片
计算机辅助制造 UG CAM培训内容UGNX6是当前最新版本的UG系列软件,是目前市场上功能最为齐全的产品设计工具之一。它以功能丰富、效率高、可靠性高而著称,是适合进行数控加工的工具软件。UGNX CAM的数控加工功能非常强大,加工方法的多样性和操…...
建设网站的网站有哪些/企业网络推广网站
2019独角兽企业重金招聘Python工程师标准>>> 数个程序员合作,开发一个项目。某个程序员A开发前端,要调用接口等。另一个程序员B开发后台管理程序。 程序员A希望后台开发的人能帮忙造些数据。为了方便程序员A创建数据,后台开发的程…...
临沂网站建设对实体企业的重要性/站长工具seo综合查询访问
2018年1月22日下午,SpiderStore母公司「北京智源环链科技有限公司」被评选为“2018区块链百强企业”并受邀出席在清华大学举办的“第一届中国区块链产业经济发展年会”。会议由清华大学互联网产业研究院联合链塔智库、赛迪区块链研究院共同主办,旨在推动…...
国内独立站建站平台排名/sem是什么意思
原文件名格式:汉字名称数字.dcm,例如:杨勇23.dcm 修改后文件名格式:IM三位数字.dcm,例如:IM023.dcm %% 重命名需打开当前文件夹再运行 % 直接读取即可 不需要重新命名 files dir(*.dcm); lenlength(files); for i1:len oldnamefiles(i)…...
广东做网站公司/网络服务提供者知道或者应当知道
一.revert to this version 和 revert changes from this version的区别 假设我们有许多个版本,版本号分别是1-10 如果我们在7这里选择revert to this version那么7之后的8,9,10的操作都会被消除 如果在7选择revert changes from this version那么7版本的修改将会…...
青浦手机网站制作/永久免费个人网站注册
考研各个科目的分值考研,是研究生入学考试的简称。考研首先要符合国家标准,其次按照程序,接下来由小编为大家整理出考研各个科目的分值,希望大家喜欢!考研各个科目的.分值英语100,政治100,数学(…...