在日常开发中数据集合经常的会用到,使用频率较高的例如 List 、Dictionary,在数据集合中每种数据结构都有他们的优缺点,所以今天笔者对常用的数据集合归纳整理,一是防止自己忘记、二是希望能够帮助到对此理解不清晰的开发者
笔者的Unity 开发版本为 2017.4.2.f2 (.NET 4.6)
有说的不准确或者错误的地方欢迎留言指正
Array
- Array:在内存上连续分配的,而且元素类型是一样的
- 优点:可以索引坐标访问 读取快 缺点:增删慢,长度不变
//Array:在内存上连续分配的,而且元素类型是一样的
//优点:可以索引坐标访问 读取快 缺点:增删慢,长度不变
int[] intArray = new int[3];
intArray[0] = 0;
string[] stringArray = new string[] { "菜鸟", "海澜" };//Array
动态数组(ArrayList)
- ArrayList 不定长的,连续分配的;
- 元素没有类型限制,任何元素都是当成object处理
- 优点:读取快 缺点:增删慢,如果是值类型,会有装箱操作
//ArrayList 不定长的,连续分配的;
//元素没有类型限制,任何元素都是当成object处理
//优点:读取快 缺点:增删慢,如果是值类型,会有装箱操作
ArrayList arrayList = new ArrayList();
arrayList.Add("菜鸟");
arrayList.Add("海澜");
arrayList.Add(9257);//add增加长度
List 详情请看MSDN备注中的性能相关
- 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
- 在链表的特点上添加先进先出特点
//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地址
- 在链表的基础上添加先进后出特点
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)}");
打印结果:
- 对应的交、补、并、补
{
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("计算差集结束");
}
打印输出
SortedSet
C#编程中HashSet和SortedSet的讲解及区别
- 也是有去重和交、叉、并、补、功能,并且可自动排序个自定义排序
IComparer<T> comparer 自定义对象要排序,就用这个指定
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);
}
打印信息
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}");
}
打印结果:
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);//先全部获取,然后一起返还
}
});
效果如下:
网友评论
task·run又是什么用法?