Unity 之数据集合解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 在日常开发中数据集合经常的会用到,使用频率较高的例如 List 、Dictionary,在数据集合中每种数据结构都有他们的优缺点,所以今天笔者对常用的数据集合归纳整理,一是防止自己忘记、二是希望能够帮助到对此理解不清晰的开发者笔者的Unity 开发版本为 2017.

在日常开发中数据集合经常的会用到,使用频率较高的例如 ListDictionary,在数据集合中每种数据结构都有他们的优缺点,所以今天笔者对常用的数据集合归纳整理,一是防止自己忘记、二是希望能够帮助到对此理解不清晰的开发者

笔者的Unity 开发版本为 2017.4.2.f2 (.NET 4.6)


有说的不准确或者错误的地方欢迎留言指正


Array

img_1987d55781843ec96522cde7d66448cd.png
  • Array:在内存上连续分配的,而且元素类型是一样的
  • 优点:可以索引坐标访问 读取快 缺点:增删慢,长度不变
            //Array:在内存上连续分配的,而且元素类型是一样的
            //优点:可以索引坐标访问  读取快     缺点:增删慢,长度不变
            int[] intArray = new int[3];
            intArray[0] = 0;
            string[] stringArray = new string[] { "菜鸟", "海澜" };//Array

动态数组(ArrayList)

img_1072eea2e3a612d79b39ea551cdec6fb.png
  • ArrayList 不定长的,连续分配的;
  • 元素没有类型限制,任何元素都是当成object处理
  • 优点:读取快 缺点:增删慢,如果是值类型,会有装箱操作
            //ArrayList  不定长的,连续分配的;
            //元素没有类型限制,任何元素都是当成object处理
            //优点:读取快            缺点:增删慢,如果是值类型,会有装箱操作
            ArrayList arrayList = new ArrayList();
            arrayList.Add("菜鸟");
            arrayList.Add("海澜");
            arrayList.Add(9257);//add增加长度

List 详情请看MSDN备注中的性能相关

img_24acf1769d12cb9f33d1f9d6c2122eec.png
  • List:也是Array,内存上都是连续摆放;不定长;泛型,保证类型安全,避免装箱拆箱
  • 优点:读取快 缺点:增删慢
            //List:也是Array,内存上都是连续摆放;不定长;泛型,保证类型安全,避免装箱拆箱
            //优点:读取快      缺点:增删慢
            List<int> intList = new List<int>() { 1, 2, 3, 4 };
            intList.Add(5);
            intList.Add(6);

LinkedList

  • LinkedList:泛型的特点;链表,元素不连续分配,每个元素都有记录前后节点
  • 节点值可以重复
  • 优点:增删方便 缺点:不能进行下标索引访问,找元素就只能遍历 查找不方便
            LinkedList<int> linkedList = new LinkedList<int>();
            linkedList.AddFirst(123);
            linkedList.AddLast(456);

            bool isContain = linkedList.Contains(123);
            LinkedListNode<int> node123 = linkedList.Find(123);  //元素123的位置  从头查找
            linkedList.AddBefore(node123, 123);
            linkedList.AddAfter(node123, 789);

Queue

img_c109c10f9b5e3590d4df2d0770fd032c.png
  • 在链表的特点上添加先进先出特点
            //Queue 就是链表  先进先出  放任务延迟执行,A不断写入日志任务  B不断获取任务去执行
            Queue<string> numbers = new Queue<string>();
            numbers.Enqueue("one");
            numbers.Enqueue("two");
            numbers.Enqueue("three");
            numbers.Enqueue("four");
            numbers.Enqueue("four");
            numbers.Enqueue("five");


Stack

Stack对应MSDN地址

img_6f599c82530575a9f2a98bed6ef20ef4.png
  • 在链表的基础上添加先进后出特点
            Stack<string> numbers = new Stack<string>();
            numbers.Push("one");
            numbers.Push("two");
            numbers.Push("three");
            numbers.Push("four");
            numbers.Push("five");//放进去

HashSet

参考文章如下

HashTable、HashSet和Dictionary的区别

国外开发者HashTable、HashSet和Dictionary的比较文章

  • 这个HashSet就厉害了,hash分布,不仅仅能动态扩容、自动去重,而且还有交、叉、并、补功能
            HashSet<string> hashSet = new HashSet<string>();
            hashSet.Add("1111");
            hashSet.Add("2222");
            hashSet.Add("3333");
            hashSet.Add("1111");
            hashSet.Add("1111");
            hashSet.Add("1111");
            Debug.Log($"第一次打印开始{new string('*', 20)}");
            foreach (var item in hashSet)
            {
                Debug.Log(item);
            }
            Debug.Log($"hashSet含有的Count为:{hashSet.Count}");

            Debug.Log($"第一次打印结束{new string('*', 20)}");
打印结果:
img_78c078aa351b3a7930a8b3ad68093014.png
  • 对应的交、补、并、补
            {
                HashSet<string> hashSet = new HashSet<string>();
                hashSet.Add("1111");
                hashSet.Add("2222");
                hashSet.Add("3333");
                hashSet.Add("A12435");
                hashSet.Add("B12435");
                hashSet.Add("C12435");

                HashSet<string> hashSet1 = new HashSet<string>();
                hashSet1.Add("1111");
                hashSet1.Add("1111");
                hashSet1.Add("1111");
                hashSet1.Add("2222");
                hashSet1.Add("3333");
                hashSet1.Add("a12435");
                hashSet1.Add("b12435");
                hashSet1.Add("c12435");

                HashSet<string> hashSet2 = new HashSet<string>();
                hashSet2.Add("1111");
                hashSet2.Add("1111");
                hashSet2.Add("1111");
                hashSet2.Add("2222");
                hashSet2.Add("3333");
                hashSet2.Add("a12435");
                hashSet2.Add("b12435");
                hashSet2.Add("c12435");

                HashSet<string> hashSet3 = new HashSet<string>();
                hashSet3.Add("1111");
                hashSet3.Add("1111");
                hashSet3.Add("1111");
                hashSet3.Add("2222");
                hashSet3.Add("3333");
                hashSet3.Add("a12435");
                hashSet3.Add("b12435");
                hashSet3.Add("c12435");

                HashSet<string> hashSet4 = new HashSet<string>();
                hashSet4.Add("1111");
                hashSet4.Add("1111");
                hashSet4.Add("1111");
                hashSet4.Add("2222");
                hashSet4.Add("3333");
                hashSet4.Add("a12435");
                hashSet4.Add("b12435");
                hashSet4.Add("c12435");

                Debug.Log("计算交集开始");
                hashSet1.IntersectWith(hashSet);//交集(hashSet1与hashSet共有的元素集合,并赋值给hashSet1)
                foreach (var item in hashSet1)
                {
                    Debug.Log(item);
                }
                Debug.Log("计算交集结束");

                Debug.Log("计算补集开始");
                hashSet2.SymmetricExceptWith(hashSet);//补集(除共有意外的所有元素集合,并赋值给hashSet2)
                foreach (var item in hashSet2)
                {
                    Debug.Log(item);
                }
                Debug.Log("计算补集结束");

                Debug.Log("计算并集开始");
                hashSet3.UnionWith(hashSet);//并集(两个集合含有的所有元素,并赋值给hashSet3)
                foreach (var item in hashSet3)
                {
                    Debug.Log(item);
                }
                Debug.Log("计算并集结束");

                Debug.Log("计算差集开始");
                hashSet4.ExceptWith(hashSet);//差集(hashSet1有而hashSet没有的元素集合,并赋值给hashSet4)
                foreach (var item in hashSet4)
                {
                    Debug.Log(item);
                }
                Debug.Log("计算差集结束");
            }

打印输出

img_ee5e1448c52dce175a29ad68e36ee14d.png
img_a44bf54ae4665f9286b67c00fc311daa.png
img_ec364bae8f2ea05c08d968f6a7e93c8c.png
img_6a848defd265a18e48cec93da0d0e23c.png

SortedSet

C#编程中HashSet和SortedSet的讲解及区别

  • 也是有去重和交、叉、并、补、功能,并且可自动排序个自定义排序

IComparer<T> comparer 自定义对象要排序,就用这个指定

img_3c8f3b3590468c2dac2f5ee4f7e317ea.png
            SortedSet<string> sortedSet = new SortedSet<string>();
            sortedSet.Add("a123456");
            sortedSet.Add("b123456");
            sortedSet.Add("c123456");
            sortedSet.Add("12435");
            sortedSet.Add("12435");
            sortedSet.Add("12435");

            foreach (var item in sortedSet)
            {
                Debug.Log(item);
            }
打印信息
img_b2d4840c3be97c7c34a43fe42b463bb8.png

Hashtable

  • Hashtable key-value 体积可以动态增加 根据key计算一个地址,然后在对应的地址中放入key - value信息
  • object-装箱拆箱问题 如果不同的key计算得到相同的地址,则第二个在前面地址上 + 1
  • 查找的时候,如果地址对应数据信息的key不对,那就 + 1查找(出现上面一条的情况下)
  • 优点:查找个数据 一次定位; 增删 一次定位; 增删查改 都很快
  • 缺点:浪费了空间,Hashtable是基于数组实现,如果数据太多,造成重复相同地址(第二条),效率下降
            Hashtable table = new Hashtable();
            table.Add("123", "456");
            table[1] = 456;
            table[2] = 789;
            table[3] = 101112;
            table[1] = "0000";
            table["海澜"] = 9257;
            foreach (DictionaryEntry objDE in table)
            {
                Debug.Log(objDE.Key.ToString());
                Debug.Log(objDE.Value.ToString());
            }
            //线程安全
            Hashtable.Synchronized(table);//只有一个线程写  多个线程读

Dictionary

出场率最高的key -value 数据集合,也是大家很熟悉的
  • 字典:泛型;key - value,增删查改 都很快;有序的
  • 典不是线程安全 安全字典用ConcurrentDictionary
            Dictionary<int, string> dic = new Dictionary<int, string>();
            dic.Add(5, "e");
            dic.Add(4, "d");
            dic.Add(3, "c");
            dic.Add(2, "b");
            dic.Add(1, "a");
            foreach (var item in dic)
            {
                Debug.Log($"Key:{item.Key}, Value:{item.Value}");
            }

SortedDictionary

  • 自动排序
        SortedDictionary<int, string> dic = new SortedDictionary<int, string>();
        dic.Add(1, "a");
        dic.Add(5, "e");
        dic.Add(3, "v");
        dic.Add(2, "b");
        dic.Add(4, "d");
        dic[6] = "f";

        foreach (var item in dic)
        {
            Debug.Log($"Key:{item.Key}, Value:{item.Value}");
        }

打印结果:

img_2f370d145d5741e6b3da39bb2647df5e.png

SortedList

  • 自动排序
        SortedList sortedList = new SortedList();//IComparer
        sortedList.Add("1", "a");
        sortedList.Add("2", "b");
        sortedList.Add("3", "c");

        var keyList = sortedList.GetKeyList();
        var valueList = sortedList.GetValueList();

        sortedList.TrimToSize();//用于最小化集合的内存开销
  • ConcurrentQueue 线程安全版本的Queue
  • ConcurrentStack线程安全版本的Stack
  • ConcurrentBag线程安全的对象集合
  • ConcurrentDictionary线程安全的Dictionary
  • BlockingCollection线程安全集合类

详情查看System.Collections.Concurrent Namespace

最后附上相应的[IDictionary选项 - 性能测试 - SortedList与SortedDictionary vs. Dictionary与Hashtable,不方便看的小伙伴可以用谷歌浏览器一键翻译,翻译比较准确


IEnumerable补充

IEnumerable经常会见到,都是知道他是迭代器,但是具体怎么个迭代,又有点可能说不清,下面笔者举个小例子

public class YieldDemo
{
    public IEnumerable<int> CustomEnumerable()
    {
        for (int i = 0; i < 10; i++)
        {
            yield return this.Get(i);
        }
    }

    public IEnumerable<int> Common()
    {
        List<int> intList = new List<int>();
        for (int i = 0; i < 10; i++)
        {
            intList.Add(this.Get(i));
        }
        return intList;
    }

    private int Get(int num)
    {
        Thread.Sleep(200);
        return num * DateTime.Now.Second;
    }
}
        Task.Run(()=> 
        {
            YieldDemo yieldDemo = new YieldDemo();
            foreach (var item in yieldDemo.CustomEnumerable())
            {
                Debug.Log(item);//按需获取,要一个拿一个
            }
            Debug.Log("*******************************************");
            foreach (var item in yieldDemo.Common())
            {
                Debug.Log(item);//先全部获取,然后一起返还
            }
        });

效果如下:

img_00af13906fcef8a132d9f7e164c87678.gif

它最主要的作用就是【按需逐步查询,避免性能浪费】【按需逐步查询,避免性能浪费】【按需逐步查询,避免性能浪费】,比如一个集合含有1000个元素,目的是需要查询到他的第二个元素,用yeild方法就可以省去而剩下的998次查询,如果是多次查询效率上的提升可想而知。

在实际开发中如果查询比较复杂,例如使用List配饰Linq中的where是一个不错的选择

img_0321b8213e6d1dcce6481266ee3c4785.png
相关文章
|
17天前
|
数据采集 存储 JavaScript
如何使用Cheerio与jsdom解析复杂的HTML结构进行数据提取
在现代网页开发中,复杂的HTML结构给爬虫技术带来挑战。传统的解析库难以应对,而Cheerio和jsdom在Node.js环境下提供了强大工具。本文探讨如何在复杂HTML结构中精确提取数据,结合代理IP、cookie、user-agent设置及多线程技术,提升数据采集的效率和准确性。通过具体示例代码,展示如何使用Cheerio和jsdom解析HTML,并进行数据归类和统计。这种方法适用于处理大量分类数据的爬虫任务,帮助开发者轻松实现高效的数据提取。
如何使用Cheerio与jsdom解析复杂的HTML结构进行数据提取
|
3天前
|
存储 关系型数据库 MySQL
技术解析:MySQL中取最新一条重复数据的方法
以上提供的两种方法都可以有效地从MySQL数据库中提取每个类别最新的重复数据。选择哪种方法取决于具体的使用场景和MySQL版本。子查询加分组的方法兼容性更好,适用于所有版本的MySQL;而窗口函数方法代码更简洁,执行效率可能更高,但需要MySQL 8.0及以上版本。在实际应用中,应根据数据量大小、查询性能需求以及MySQL版本等因素综合考虑,选择最合适的实现方案。
22 6
|
18天前
|
XML JSON API
淘宝京东商品详情数据解析,API接口系列
淘宝商品详情数据包括多个方面,如商品标题、价格、图片、描述、属性、SKU(库存量单位)库存、视频等。这些数据对于买家了解商品详情以及卖家管理商品都至关重要。
|
19天前
|
设计模式 存储 人工智能
深度解析Unity游戏开发:从零构建可扩展与可维护的游戏架构,让你的游戏项目在模块化设计、脚本对象运用及状态模式处理中焕发新生,实现高效迭代与团队协作的完美平衡之路
【9月更文挑战第1天】游戏开发中的架构设计是项目成功的关键。良好的架构能提升开发效率并确保项目的长期可维护性和可扩展性。在使用Unity引擎时,合理的架构尤为重要。本文探讨了如何在Unity中实现可扩展且易维护的游戏架构,包括模块化设计、使用脚本对象管理数据、应用设计模式(如状态模式)及采用MVC/MVVM架构模式。通过这些方法,可以显著提高开发效率和游戏质量。例如,模块化设计将游戏拆分为独立模块。
44 3
|
12天前
|
存储 JSON API
Python编程:解析HTTP请求返回的JSON数据
使用Python处理HTTP请求和解析JSON数据既直接又高效。`requests`库的简洁性和强大功能使得发送请求、接收和解析响应变得异常简单。以上步骤和示例提供了一个基础的框架,可以根据你的具体需求进行调整和扩展。通过合适的异常处理,你的代码将更加健壮和可靠,为用户提供更加流畅的体验。
39 0
|
19天前
|
图形学 开发者
透视与正交之外的奇妙视界:深入解析Unity游戏开发中的相机与视角控制艺术,探索打造沉浸式玩家体验的奥秘与技巧
【8月更文挑战第31天】在Unity中,相机不仅是玩家观察游戏世界的窗口,更是塑造氛围和引导注意力的关键工具。通过灵活运用相机系统,开发者能大幅提升游戏的艺术表现力和沉浸感。本文将探讨如何实现多种相机控制,包括第三人称跟随和第一人称视角,并提供实用代码示例。
35 0
|
21天前
|
监控 网络协议 Java
Tomcat源码解析】整体架构组成及核心组件
Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
Tomcat源码解析】整体架构组成及核心组件
|
1月前
|
存储 NoSQL Redis
redis 6源码解析之 object
redis 6源码解析之 object
54 6
|
6天前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
什么是线程池?从底层源码入手,深度解析线程池的工作原理
|
6天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。

热门文章

最新文章

推荐镜像

更多