《Unity3D高级编程之进阶主程》第一章 C#要点技术(一) - List 底层源码剖析

List内部是用数组实现的,并且当没有给予指定容量时,初始的容量为0。

Add接口

int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;

        每次容量不够的时候,整个数组的容量都会扩充一倍,_defaultCapacity 是容量的默认值为4。因此整个扩充的路线为4,8,16,32,64,128,256,512,1024…依次类推。

        List使用数组形式作为底层数据结构,好处是使用索引方式提取元素很快,但在扩容的时候就会很糟糕,每次new数组都会造成内存垃圾,这给垃圾回收GC带来了很多负担。

        如果数量不得当也会浪费大量内存空间,比如当元素数量为 520 时,List 就会扩容到1024个元素,如果不使用剩余的504个空间单位,就造成了大部分的内存空间的浪费。

Remove接口

RemoveAt 的原理其实就是用 Array.Copy 对数组进行覆盖。

IndexOf 启用的是 Array.IndexOf 接口来查找元素的索引位置,这个接口本身内部实现是就是按索引顺序从0到n对每个位置的比较,复杂度为O(n)

Insert 接口

        Insert插入元素时,使用的用拷贝数组的形式,将数组里的指定元素后面的元素向后移动一个位置。

Clear 接口

        Clear接口在调用时并不会删除数组,而只是将数组中的元素清零,并设置 _size 为 0 而已,用于虚拟地表明当前容量为0。

ToArray接口

        重新new了一个指定大小的数组,再将本身数组上的内容考别到新数组上,再返回出来。

Enumerator 枚举迭代部分

public Enumerator GetEnumerator() {
    return new Enumerator(this);
}

/// <internalonly/>
IEnumerator<T> IEnumerable<T>.GetEnumerator() {
    return new Enumerator(this);
}

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
    return new Enumerator(this);
}

        每次获取迭代器时,Enumerator 每次都是被new出来,如果大量使用迭代器的话,比如foreach就会造成大量的垃圾对象。尽量不要用foreach

Sort 接口

 使用了 Array.Sort 接口进行排序,使用的是快速排序方式进行排序, 排序的效率为O(nlogn)。

总结

        List 并不是高效的组件,真实情况是,他比数组的效率还要差的多,他只是个兼容性比较强得组件而已,好用,但效率差。        

问题
  1. List 的效率并不高,只是通用性强而已,大部分的算法都使用的是线性复杂度的算法,这种线性算法当遇到规模比较大的计算量级时就会导致CPU的大量损耗。
  2. List的内存分配方式也极为不合理,当List里的元素不断增加时,会多次重新new数组,导致原来的数组被抛弃,最后当GC被调用时造成回收的压力。
  3. List是线程不安全的,它并没有对多线程下做任何锁或其他同步操作。并发情况下,无法判断 _size++ 的执行顺序。

解决
  1. 不再使用有线性算法的接口,自己重写一套,但凡要优化List 中的线性算法的地方都使用,我们自己制作的工具类。
  2. 提前告知 List 对象最多会有多少元素在里面,这样的话 List 就不会因为空间不够而抛弃原有的数组,去重新申请数组了。
  3. 当我们在多线程间使用 List 时加上安全机制。

  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值