參考地址:https://blog.csdn.net/qiaoquan3/article/details/51380992 1、集合set:純粹的數據集合 2、線性結構:一對一的,數組 3、樹形結構:一對多的,菜單/文件夾/類別/屬性控制項/表達式目錄樹 4、圖形/網狀結構:多對多,地圖應用比較多,網 ...
參考地址:https://blog.csdn.net/qiaoquan3/article/details/51380992
1、集合set:純粹的數據集合
2、線性結構:一對一的,數組
3、樹形結構:一對多的,菜單/文件夾/類別/屬性控制項/表達式目錄樹
4、圖形/網狀結構:多對多,地圖應用比較多,網站的應用比較少
線性結構:
Array/ArrayList/List/LinkedList/Queue/Stack/HastSet/SortedSet/Hashtable/SortedList/Dictionary/SortedDictionary
IEnumerable、ICollection、IList、IQueryable
介面是標機功能的,不同的介面岔開,就是為了介面隔離;雖然我們介面內容也可以復用。
IEnumerable任何數據集合,都實現了的,為不同的數據結構,提供了統一數據訪問方式,這個就是迭代器模式。
1、記憶體連續存儲,節約空間,可以索引訪問,讀取速度快,增刪慢
Array:在記憶體上連續分配的,而且元素類型是一樣的。
int[] intArray = new int[3]; intArray[0] = 123; string[] stringArray = new string[] { "123", "234" };//Array
ArrayList:不定長的,連續分配的;元素沒有類型限制,任何元素都是當成object處理,如果是值類型,會有裝箱操作;讀取快,增刪慢。
ArrayList arrayList = new ArrayList(); arrayList.Add("Bingle1"); arrayList.Add("Bingle2"); arrayList.Add(32);//add增加長度 //arrayList[4] = 26;//索引複製,不會增加長度 //刪除數據 //arrayList.RemoveAt(4); var value = arrayList[2]; arrayList.RemoveAt(0); arrayList.Remove("Bingle2");
List<T>:也是Array,記憶體上都是連續拜訪的;不定長;泛型,保證類型安全,避免裝箱拆箱;讀取快,增刪慢。
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";//異常的 foreach (var item in intList) { }
2、非連續拜訪的,存儲數據+地址,找書的話就只能順序查找,讀取就比較慢,增刪快
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<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()}'"); Console.WriteLine($"Peek at next item to dequeue: { numbers.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<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}");
隊列是沒有底的瓶子,棧是有底的瓶子
集合:純粹的集合,容器,東西丟進去,唯一性,無序的。
HashSet:hash分佈,元素間沒有關係,動態增加容量,去重的。統計用戶IP;IP投票;交叉並補;二次好友/間接關註/粉絲集合
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<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);//交
SortSet:排序的集合;去重而且排序;統計排名,每統計一個就丟進去集合
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"); 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);//交
讀取和增刪都快的,有沒有?有,hash散列,字典。是key-value,一段連續空間放value(開闢的空間比用到的多,hash使用空間換性能),基於key散列計算得到地址索引,這樣讀取快,但是沒有數組快。增刪也快,刪除時也是計算位置,增加也不影響別人。代價就是,肯定會出現2個key(散列衝突),散列結果一致,可以讓第二次的+1;可能會造成效率的降低,尤其是數據量大的情況下,以前測試Dictionary在3W條左右的時候,性能愛是下降的厲害。
Hashtable---key-value,體積可以動態增加,拿著key計算下一個地址,然後放入key-value;object-裝箱茶香,如果不同的key得到相同的地址,第二個在前面地址上+1;查找的時候,如果地址對應數據的key不對,那就+1查找。。
浪費了空間,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);//只有一個線程寫 多個線程讀
字典:泛型;key - value,增刪查改 都很快;有序的。但是欄位不是線程安全的,ConcurrentDictionary
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"; dic.Add(4, "HuHu"); foreach (var item in dic) { Console.WriteLine($"Key:{item.Key}, Value:{item.Value}"); }
我們來看一下List,如下圖
List集合為什麼會繼承這麼多介面呢?
1、ICollection:
Count、IsReadOnly、Add、Clear、Contains、CopyTo、Clear
2、IList:
T this[int index] (索引)、IndexoOf、.....
3、IEnumerable:
遍歷才會去查詢比較,迭代器 yield
GetEnumerator:Current、MoveNext、Reset
任何數據集合,都實現了IEnumerable,為不同的數據結構提供了統一的數據訪問方式,這個就是迭代器模式。
4、IQueryable:
表達式目錄樹的解析,延遲到遍歷的時候才去執行,EF的延遲查詢
IQueryProvider Provider{get;}
yield是語法糖,編譯時由編譯器生成Iterrator的代碼,包括movenext current reset
含有yield的函數說明它是一個生成器,而不是普通的函數。當程式運行到yield這一行時,該函數會返回值,並保存當前域的所有變數狀態;等到該函數下一次被調用時,會從上一次中斷的地方開始執行,一直遇到下一個yield, 程式返回值, 併在此保存當前狀態; 如此反覆,直到函數正常執行完成。
迭代器模式是設計模式中行為模式(behavioral pattern)的一個例子,他是一種簡化對象間通訊的模式,也是一種非常容易理解和使用的模式。簡單來說,迭代器模式使得你能夠獲取到序列中的所有元素 而不用關心是其類型是array,list,linked list或者是其他什麼序列結構。這一點使得能夠非常高效的構建數據處理通道(data pipeline)。
--即數據能夠進入處理通道,進行一系列的變換,或者過濾,然後得到結果。事實上,這正是LINQ的核心模式。
在.NET中,迭代器模式被IEnumerator和IEnumerable及其對應的泛型介面所封裝。如果一個類實現了IEnumerable接 口,那麼就能夠被迭代;調用GetEnumerator方法將返回IEnumerator介面的實現,它就是迭代器本身。迭代器類似資料庫中的游標,他是 數據序列中的一個位置記錄。迭代器只能向前移動,同一數據序列中可以有多個迭代器同時對數據進行操作。
下麵是一個yield的一個簡單Demo:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class YieldShow { public IEnumerable<int> CreateEnumerable() { try { Console.WriteLine("{0} CreateEnumerable()方法開始", DateTime.Now); for (int i = 0; i < 5; i++) { Console.WriteLine("{0}開始 yield {1}", DateTime.Now, i); yield return i; Console.WriteLine("{0}yield 結束", DateTime.Now); if (i == 4) { yield break;//直接終結迭代 4會出現的,, } } Console.WriteLine("{0} Yielding最後一個值", DateTime.Now); yield return -1; Console.WriteLine("{0} CreateEnumerable()方法結束", DateTime.Now); } finally { Console.WriteLine("停止迭代!"); } } IEnumerable<int> iterable = this.CreateEnumerable();//1 不會直接執行 //IEnumerator iterator = iterable.GetEnumerator(); IEnumerator<int> iterator = iterable.GetEnumerator(); Console.WriteLine("開始迭代"); while (true) { Console.WriteLine("調用MoveNext方法……"); Boolean result = iterator.MoveNext();//2 正式開啟CreateEnumerable Console.WriteLine("MoveNext方法返回的{0}", result); if (!result) { break; } Console.WriteLine("獲取當前值……"); Console.WriteLine("獲取到的當前值為{0}", iterator.Current); }View Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class YieldDemo { public IEnumerable<int> Power() { for (int i = 0; i < 10; i++) { yield return this.Get(i); //Console.WriteLine("這裡再來一次"); //yield return this.Get(i) + 1; } } 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(2000); return num * DateTime.Now.Second; } } YieldDemo yieldDemo = new YieldDemo(); foreach (var item in yieldDemo.Power()) { Console.WriteLine(item);//按需獲取,要一個拿一個 if (item > 100) break; } Console.WriteLine("*******************************************"); foreach (var item in yieldDemo.Common()) { Console.WriteLine(item);//先全部獲取,然後一起返還 if (item > 100) break; }View Code
dynamic關鍵字:
.NET Framework4.0出現的,讓程式有了弱類型的特點;
強類型特點:
編譯時完成安全檢查
弱類型:
運行時才檢查類型
object A = new YieldDemo(); //A.Power(); Type type = A.GetType(); MethodInfo method = type.GetMethod("Power"); method.Invoke(A, null); dynamic dA = A; dA.Power(); //1 代替反射 2 數據綁定方便 3 跟C++交互方便 //性能比反射高 dynamic str = "abcd";//任何跟dynamic交互,都變成dynamic Console.WriteLine(str.Length); Console.WriteLine(str.Substring(1));