一、內存上連續存儲,節約空間,可以索引訪問,讀取快,增刪慢
- Array:在內存上連續分配的,而且元素類型是一樣的,可以坐標訪問;讀取快--增刪慢,長度不變
{
//Array:在內存上連續分配的,而且元素類型是一樣的
//可以坐標訪問 讀取快--增刪慢,長度不變
Console.WriteLine("***************Array******************");
int[] intArray = new int[3];
intArray[0] = 123;
string[] strArray = new string[] { "123", "234" };//Array
}
- ArrayList:不定長的,連續分配的;元素沒有類型限制,任何元素都是當成object處理,如果是值類型,會有裝箱操作;讀取快--增刪慢
{
//ArrayList 不定長的,連續分配的;
//元素沒有類型限制,任何元素都是當成object處理,如果是值類型,會有裝箱操作
//讀取快--增刪慢
Console.WriteLine("***************ArrayList******************");
ArrayList arrayList = new ArrayList();
arrayList.Add(true);
arrayList.Add("Is");
arrayList.Add(32);//add增加長度
//arrayList[4] = 26;//索引復制,不會增加長度
//刪除數據
//arrayList.RemoveAt(4);
var value = arrayList[2];
arrayList.RemoveAt(0);
arrayList.Remove(true);
}
- List:也是Array,內存上都是連續擺放;不定長;泛型,保證類型安全,避免裝箱拆箱;讀取快--增刪慢
{
//List:也是Array,內存上都是連續擺放;不定長;泛型,保證類型安全,避免裝箱拆箱
//讀取快--增刪慢
Console.WriteLine("***************List<T>******************");
List<int> intList = new List<int>() { 1, 2, 3, 4 };
intList.Add(123);
intList.Add(123);
//intList.Add("123");
//intList[0] = 123;
List<string> stringList = new List<string>();
//stringList[0] = "123";//異常的
}
二、非連續擺放,存儲數據+地址,找數據的話就只能順序查找,讀取慢;增刪快
- 鏈表LinkedList:泛型;鏈表,元素不連續分配,每個元素都有記錄前后節點;節點值可以重復;不能下標訪問,找元素就只能遍歷,查找慢;增刪快
{
//LinkedList:泛型的特點;鏈表,元素不連續分配,每個元素都有記錄前后節點
//節點值可以重復
//能不能下標訪問?不能,找元素就只能遍歷 查找不方便
//增刪 就比較方便
Console.WriteLine("***************LinkedList<T>******************");
LinkedList<int> linkedList = new LinkedList<int>();
//linkedList[3]
linkedList.AddFirst(123);//添加為第一個節點元素
linkedList.AddLast(456);//添加為最后一個節點元素
bool isContain = linkedList.Contains(123);
LinkedListNode<int> node123 = linkedList.Find(123); //元素123的位置 從頭查找
linkedList.AddBefore(node123, 123);//節點不存在,會報錯
linkedList.AddBefore(node123, 123);//在指定節點前新增元素
linkedList.AddAfter(node123, 9);//在指定節點后新增元素
linkedList.Remove(456);//刪除指定值,不存在會報錯
linkedList.Remove(node123);//刪除指定節點
linkedList.RemoveFirst();//刪除第一個元素
linkedList.RemoveLast();//刪除最后一個元素
linkedList.Clear();
}
- 隊列Queue:就是鏈表,先進先出;
放任務延遲執行,A不斷寫入日志任務 B不斷獲取任務去執行
{
//Queue 就是鏈表 先進先出 放任務延遲執行,A不斷寫入日志任務 B不斷獲取任務去執行
Console.WriteLine("***************Queue<T>******************");
Queue<string> numbers = new Queue<string>();
numbers.Enqueue("one");//添加對象到隊列末尾
numbers.Enqueue("two");
numbers.Enqueue("three");
numbers.Enqueue("four");
numbers.Enqueue("four");
numbers.Enqueue("five");
foreach (string number in numbers)
{
Console.WriteLine(number);
}
Console.WriteLine($"Dequeuing '{numbers.Dequeue()}'");//Dequeue方法 移除並返回隊列的第一個元素
Console.WriteLine($"Peek at next item to dequeue: { numbers.Peek()}");//Peek方法 返回隊列的第一個元素 但不移除元素
Console.WriteLine($"Dequeuing '{numbers.Dequeue()}'");
Queue<string> queueCopy = new Queue<string>(numbers.ToArray());
foreach (string number in queueCopy)
{
Console.WriteLine(number);
}
Console.WriteLine($"queueCopy.Contains(\"four\") = {queueCopy.Contains("four")}");
queueCopy.Clear();
Console.WriteLine($"queueCopy.Count = {queueCopy.Count}");
}
- 棧Stack:就是鏈表 先進后出 解析表達式目錄樹的時候,先產生的數據后使用;操作記錄為命令,撤銷的時候是倒序的
//隊列是沒瓶底的瓶子,棧是有瓶底的瓶子
{
//Stack 就是鏈表 先進后出 解析表達式目錄樹的時候,先產生的數據后使用
//操作記錄為命令,撤銷的時候是倒序的
Console.WriteLine("***************Stack<T>******************");
Stack<string> numbers = new Stack<string>();
numbers.Push("one");
numbers.Push("two");
numbers.Push("three");
numbers.Push("four");
numbers.Push("five");//放進去
foreach (string number in numbers)
{
Console.WriteLine(number);
}
Console.WriteLine($"Pop '{numbers.Pop()}'");//獲取並移除
Console.WriteLine($"Peek at next item to dequeue: { numbers.Peek()}");//獲取不移除
Console.WriteLine($"Pop '{numbers.Pop()}'");
Stack<string> stackCopy = new Stack<string>(numbers.ToArray());
foreach (string number in stackCopy)
{
Console.WriteLine(number);
}
Console.WriteLine($"stackCopy.Contains(\"four\") = {stackCopy.Contains("four")}");
stackCopy.Clear();
Console.WriteLine($"stackCopy.Count = {stackCopy.Count}");
}
三、Set 純粹的集合,容器,唯一性
- HashSet:hash分布,元素間沒關系,動態增加容量;去重
使用場景:統計用戶IP--IP投票;交叉並補--二次好友/間接關注/粉絲合集
{
//集合:hash分布,元素間沒關系,動態增加容量 去重
//統計用戶IP;IP投票 交叉並補--二次好友/間接關注/粉絲合集
Console.WriteLine("***************HashSet<string>******************");
HashSet<string> hashSet = new HashSet<string>();
hashSet.Add("123");
hashSet.Add("689");
hashSet.Add("456");
hashSet.Add("12435");
hashSet.Add("12435");
hashSet.Add("12435");
//hashSet[0];
foreach (var item in hashSet)
{
Console.WriteLine(item);
}
Console.WriteLine(hashSet.Count);
Console.WriteLine(hashSet.Contains("12345"));
{
HashSet<string> hashSet1 = new HashSet<string>();
hashSet1.Add("123");
hashSet1.Add("689");
hashSet1.Add("789");
hashSet1.Add("12435");
hashSet1.Add("12435");
hashSet1.Add("12435");
hashSet1.SymmetricExceptWith(hashSet);//補
hashSet1.UnionWith(hashSet);//並
hashSet1.ExceptWith(hashSet);//差
hashSet1.IntersectWith(hashSet);//交
// 找出共同的好友
}
hashSet.ToList();
hashSet.Clear();
}
- SortedSet排序的集合:去重 而且排序
使用場景:統計排名--每統計一個就丟進去集合
{
//排序的集合:去重 而且排序
//統計排名--每統計一個就丟進去集合
Console.WriteLine("***************SortedSet<string>******************");
SortedSet<string> sortedSet = new SortedSet<string>();
//IComparer<T> comparer 自定義對象要排序,就用這個指定
sortedSet.Add("123");
sortedSet.Add("689");
sortedSet.Add("456");
sortedSet.Add("12435");
sortedSet.Add("12435");
sortedSet.Add("12435");
foreach (var item in sortedSet)
{
Console.WriteLine(item);
}
Console.WriteLine(sortedSet.Count);
Console.WriteLine(sortedSet.Contains("12345"));
{
SortedSet<string> sortedSet1 = new SortedSet<string>();
sortedSet1.Add("123");
sortedSet1.Add("689");
sortedSet1.Add("456");
sortedSet1.Add("12435");
sortedSet1.Add("12435");
sortedSet1.Add("12435");
sortedSet1.SymmetricExceptWith(sortedSet);//補
sortedSet1.UnionWith(sortedSet);//並
sortedSet1.ExceptWith(sortedSet);//差
sortedSet1.IntersectWith(sortedSet);//交
}
sortedSet.ToList();
sortedSet.Clear();
}
四、讀取&增刪都快? 有 hash散列 字典
key-value,一段連續有限空間放value(開辟的空間比用到的多,hash是用空間換性能),基於key散列計算得到地址索引,這樣讀取快;增刪也快,刪除時也是計算位置,增加也不影響別人;會出現2個key(散列沖突),散列結果一致18,可以讓第二次的+1;可能會造成效率的降低,尤其是數據量大的情況下,以前測試過dictionary在3w條左右性能就開始下降的厲害
- Hashtable key-value:體積可以動態增加 拿着key計算一個地址,然后放入key - value;object-裝箱拆箱 如果不同的key得到相同的地址,第二個在前面地址上 + 1;查找的時候,如果地址對應數據的key不對,那就 + 1查找。。;浪費了空間,Hashtable是基於數組實現;查找個數據 一次定位; 增刪 一次定位; 增刪查改 都很快
{
//Hashtable key-value 體積可以動態增加 拿着key計算一個地址,然后放入key - value
//object-裝箱拆箱 如果不同的key得到相同的地址,第二個在前面地址上 + 1
//查找的時候,如果地址對應數據的key不對,那就 + 1查找。。
//浪費了空間,Hashtable是基於數組實現
//查找個數據 一次定位; 增刪 一次定位; 增刪查改 都很快
//浪費空間,數據太多,重復定位定位,效率就下去了
Console.WriteLine("***************Hashtable******************");
Hashtable table = new Hashtable();
table.Add("123", "456");
table[234] = 456;
table[234] = 567;
table[32] = 4562;
table[1] = 456;
table["eleven"] = 456;
foreach (DictionaryEntry objDE in table)
{
Console.WriteLine(objDE.Key.ToString());
Console.WriteLine(objDE.Value.ToString());
}
//線程安全
Hashtable.Synchronized(table);//只有一個線程寫 多個線程讀
}
- Dictionary字典:泛型;key - value,增刪查改 都很快;有序的
{
//字典:泛型;key - value,增刪查改 都很快;有序的
// 字典不是線程安全 ConcurrentDictionary
Console.WriteLine("***************Dictionary******************");
Dictionary<int, string> dic = new Dictionary<int, string>();
dic.Add(1, "HaHa");
dic.Add(5, "HoHo");
dic.Add(3, "HeHe");
dic.Add(2, "HiHi");
dic.Add(4, "HuHu1");
dic[4] = "HuHu";//相同key替換原值
dic.Add(4, "HuHu");//相同key,會報錯
foreach (var item in dic)
{
Console.WriteLine($"Key:{item.Key}, Value:{item.Value}");
}
}
- SortedDictionary 排序字典
{
Console.WriteLine("***************SortedDictionary******************");
SortedDictionary<int, string> dic = new SortedDictionary<int, string>();
dic.Add(1, "HaHa");
dic.Add(5, "HoHo");
dic.Add(3, "HeHe");
dic.Add(2, "HiHi");
dic.Add(4, "HuHu1");
dic[4] = "HuHu";//相同key替換原值
dic.Add(4, "HuHu");//相同key,會報錯
foreach (var item in dic)
{
Console.WriteLine($"Key:{item.Key}, Value:{item.Value}");
}
}
- SortedList 排序集合
{
Console.WriteLine("***************SortedList******************");
SortedList sortedList = new SortedList();//IComparer
sortedList.Add("First", "Hello");
sortedList.Add("Second", "World");
sortedList.Add("Third", "!");
sortedList["Third"] = "~~";//相同key替換原值
sortedList.Add("Fourth", "!");
sortedList.Add("Fourth", "!");//重復的Key Add會錯
sortedList["Fourth"] = "!!!";
var keyList = sortedList.GetKeyList();
var valueList = sortedList.GetValueList();
sortedList.TrimToSize();//用於最小化集合的內存開銷
sortedList.Remove("Third");
sortedList.RemoveAt(0);
sortedList.Clear();
}
五、線程安全的幾種數據結構
{
//ConcurrentQueue 線程安全版本的Queue
//ConcurrentStack線程安全版本的Stack
//ConcurrentBag線程安全的對象集合
//ConcurrentDictionary線程安全的Dictionary
//BlockingCollection
}
- 本文參考文檔:
https://blog.csdn.net/qiaoquan3/article/details/51380992 - 微軟官方文檔:
- System.Collections:https://docs.microsoft.com/en-us/dotnet/api/system.collections?view=netframework-4.8
- System.Collections.Concurrent:https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent?view=netframework-4.8
- System.Collections.Generic:https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic?view=netframework-4.8