【原創】一個支持極限大小的數組MaxArray,且節省內存
大家好,我寫了一個支持極限大小的數組MaxArray,很有用的,希望大家喜歡~~
問:.net類庫不是自帶了一個嗎,幹嘛還要自己寫一個?好在哪裏?
答:數組可以在創建後立即訪問範圍內的任意索引位置,而不需要依次添加,可以跳躍添加,但它的缺點就是創建時立即分配全部內存,比如你連續新建幾個int[] arr=new int[int.maxvalue]這樣的極限大的數組,會遇到內存溢出異常。
問:要節省內存,可以用ArrayList或List<T>這些,幹嘛非得自己寫一個?
答:arraylist或者List<T>雖然節省內存,但是它們缺少數組的一個功能:初始化後立即可以隨機存取訪問任意索引位置,而只能從索引0開始一個一個添加元素
問:這個極限數組的獨到之處和使用場景是怎樣的呢?
答:我的這個極限數組就是結合這兩種類的優點,既可以象數組一樣創建後所有索引項立即可用,可以跳躍存取,又可以象arraylist和list<T>一樣節省內存,沒有實際使用過的索引位置並不實際分配內存,但這個索引確實存在,可以任意存取使用。
它的適用場合就和數組的適用場合是重合的--可惜性能不太好,存取速度大約是數組的5倍到6倍的樣子,所以,被排擠到只適合一些極限大的數組的場合,代替數組。
這很有用,在一些別扭的業務場景,或者腦洞大開的奇葩算法中,有了這個可以讓以前數組力不從心的設計方案也能實現。
或者你可以反過來想:有了這個東東,以前一些只停留在想象中的業務處理方式、軟件的類架構、設計模式、算法,必須要用到數組的隨機訪問特點,但極限大的數組又做不到的,只好換種別扭的方式實現,現在好了,有了我寫的這個極限數組,不用曲裏拐彎的實現了,可以平推過去。是設計上、思路上的一個豁然開朗的重要東東。
我有許多原創的東東,以後會陸續發上來。太多人太多文章是屬於“跟隨、學習、使用"類型的,我這樣的”創建“型的人很少,希望大家多多關註本博客。
以下是代碼,類源代碼、使用示例、性能測試代碼都有:
using System; using System.Collections.Generic; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { //---------以下是---功能展示區--------------------------------------------------------------MaxArray<int> arrInt = new MaxArray<int>(int.MaxValue); int i1 = arrInt[8]; arrInt[8] = 133; int i2 = arrInt[8]; //這是初始化時指定的大小,初始化時實際並未分配內存,是一個“不存在的索引”。 //但是在這個範圍內你都可以把它當作已分配內存的一樣任意直接賦值。 int count = arrInt.Count_Inited; //這個是實際賦值過的有意義的元素個數。 int count_userd = arrInt.Count_RealUserd; arrInt.RemovValueAt(8); int i3 = arrInt[8]; int count2 = arrInt.Count_Inited; //這裏可以看到,經過前面RemovValueAt(8)操作後,實際有意義元素減少了一個,但初始化指定的元素個數並沒有變化 //在移除一個實際有意義的元素的時候,請使用RemovValueAt()方法,因為這樣會同時維護count_userd值。 int count_userd2 = arrInt.Count_RealUserd; MaxArray<Student> arrStudents = new MaxArray<Student>(int.MaxValue); Student stu1 = arrStudents[5]; arrStudents[5] = new Student(); Student stu2 = arrStudents[5]; arrStudents.RemovValueAt(5); Student stu3 = arrStudents[5]; //這是一個奇葩用法,int索引值和char索引值混合使用. //是的,你沒有看錯,這其實可以看做支持int值key或char值key的一個奇葩字典,可惜性能幹不過正版字典。 MaxArray<object> arrchar = new MaxArray<object>(char.MaxValue); object o1 = arrchar[‘a‘]; arrchar[‘a‘] = new object(); object o2 = arrchar[‘a‘]; object o3 = arrchar[76]; arrchar[76] = new object(); object o4 = arrchar[76]; //--------以下是----性能測試區------------------------------------------------------------------ System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); MaxArray<Student> arrStudents2 = new MaxArray<Student>(2000000); for(int idx=0;idx< 2000000; idx++) { arrStudents2[idx] = new Student(); } stopwatch.Stop(); string 極限數組的賦值耗時 = stopwatch.Elapsed.TotalSeconds.ToString(); stopwatch.Restart(); Student[] arrStudent3 = new Student[2000000]; for (int idx = 0; idx < 2000000; idx++) { arrStudent3[idx] = new Student(); } stopwatch.Stop(); string 原生數組的賦值耗時 = stopwatch.Elapsed.TotalSeconds.ToString(); stopwatch.Restart(); Dictionary<int, Student> dicStudent = new Dictionary<int,Student>(); for (int idx = 0; idx < 2000000; idx++) { dicStudent.Add(idx, new Student()); } stopwatch.Stop(); string 字典的賦值耗時 = stopwatch.Elapsed.TotalSeconds.ToString(); } public class MaxArray<T> { //作者博客http://www.cnblogs.com/bkyguestwc/。2017年6月8日 public int Count_Inited; public int Count_RealUserd; private int startidx; private int step; private int group0maxIdx; private int group1maxIdx; private int group2maxIdx; private int group3maxIdx; private MaxArray<T> Groups0; private MaxArray<T> Groups1; private MaxArray<T> Groups2; private MaxArray<T> Groups3; //只用在末級,存儲最終對象值 private T Objs0; private T Objs1; private T Objs2; private T Objs3; public MaxArray(int getlenthe) { Count_Inited = getlenthe; Count_RealUserd = 0; int initlengthe = getlenthe; if (initlengthe <= 4) { initlengthe = 4; } else { if (initlengthe <= 16) { initlengthe = 16; } else { if (initlengthe <= 64) { initlengthe = 64; } else { if (initlengthe <= 256) { initlengthe = 256; } else { if (initlengthe <= 1024) { initlengthe = 1024; } else { if (initlengthe <= 4096) { initlengthe = 4096; } else { if (initlengthe <= 16384) { initlengthe = 16384; } else { if (initlengthe <= 65536) { initlengthe = 65536; } else { if (initlengthe <= 262144) { initlengthe = 262144; } else { if (initlengthe <= 1048576) { initlengthe = 1048576; } else { if (initlengthe <= 4194304) { initlengthe = 4194304; } else { if (initlengthe <= 16777216) { initlengthe = 16777216; } else { if (initlengthe <= 67108864) { initlengthe = 67108864; } else { if (initlengthe <= 268435456) { initlengthe = 268435456; } else { if (initlengthe <= 1073741824) { initlengthe = 1073741824; } else { initlengthe = 2147483647; } } } } } } } } } } } } } } } if (initlengthe == 2147483647) {//這些就只能分兩份了 startidx = 0; step = 1073741824; group0maxIdx = 1073741823; group1maxIdx = 2147483647; group2maxIdx = 0; group3maxIdx = 0; Groups0 = new MaxArray<T>(0, 1073741823); Groups1 = new MaxArray<T>(1073741824, 2147483647); Groups2 = null; Groups3 = null; } else {//這之下的都是可以正常分四份的 startidx = 0; step = initlengthe / 4; group0maxIdx =step - 1; group1maxIdx = group0maxIdx + step; group2maxIdx = group1maxIdx + step; group3maxIdx = group2maxIdx + step; } string mm = string.Empty; } private MaxArray(int getstartidx, int maxidx) { Count_Inited = 0; Count_RealUserd = 0; startidx = getstartidx; int lanth = maxidx - (startidx - 1); step = lanth / 4; group0maxIdx = startidx + step - 1; group1maxIdx = group0maxIdx + step; group2maxIdx = group1maxIdx + step; group3maxIdx = group2maxIdx + step; } public T this[int index] { get { //檢查索引範圍 if (index < 0 || index >= Count_Inited) { throw new Exception("索引越界"); } else { T needValue; needValue = FindNeedValue(index); return needValue; } } set {//設置指定節點值 if (index < 0 || index >= Count_Inited) { throw new Exception("索引越界"); } else { Count_RealUserd++; SetNeedValue(index, value); } } } public void RemovValueAt(int idx) { Count_RealUserd--; RemovValue(idx); } private void RemovValue(int idx) { if (step == 1) {//這就是末級,不用再往下級找了 if (idx == group0maxIdx) { Objs0 = default(T); } else { if (idx == group1maxIdx) { Objs1 = default(T); } else { if (idx == group2maxIdx) { Objs2 = default(T); } else { if (idx == group3maxIdx) { Objs3 = default(T); } else { throw new Exception("意外值"); } } } } } else {//不是末級,要去下級找 if (idx <= group0maxIdx) {//決定進入Group0 Groups0.RemovValue(idx); } else { if (idx <= group1maxIdx) {//決定進入Group1 Groups1.RemovValue(idx); } else { if (idx <= group2maxIdx) {//決定進入Group2 Groups2.RemovValue(idx); } else { if (idx <= group3maxIdx) {//決定進入Group3 Groups3.RemovValue(idx); } else { throw new Exception("意外值"); } } } } } } private void SetNeedValue(int idx, T getValue) { if (step == 1) {//這就是末級,不用再往下級找了 if (idx == group0maxIdx) { Objs0 = getValue; } else { if (idx == group1maxIdx) { Objs1 = getValue; } else { if (idx == group2maxIdx) { Objs2 = getValue; } else { if (idx == group3maxIdx) { Objs3 = getValue; } else { throw new Exception("意外值"); } } } } } else {//不是末級,要去下級找 if (idx <= group0maxIdx) {//決定進入Group0 if (Groups0 == null) { Groups0 = new MaxArray<T>(startidx, group0maxIdx); } Groups0.SetNeedValue(idx, getValue); } else { if (idx <= group1maxIdx) {//決定進入Group1 if (Groups1 == null) { Groups1 = new MaxArray<T>(group0maxIdx + 1, group1maxIdx); } Groups1.SetNeedValue(idx, getValue); } else { if (idx <= group2maxIdx) {//決定進入Group2 if (Groups2 == null) { Groups2 = new MaxArray<T>(group1maxIdx + 1, group2maxIdx); } Groups2.SetNeedValue(idx, getValue); } else { if (idx <= group3maxIdx) {//決定進入Group3 if (Groups3 == null) { Groups3 = new MaxArray<T>(group2maxIdx + 1, group3maxIdx); } Groups3.SetNeedValue(idx, getValue); } else { throw new Exception("意外值"); } } } } } } private T FindNeedValue(int idx) { T needValue; needValue = default(T); if (step == 1) {//這就是末級,不用再往下級找了 if (idx == group0maxIdx) { needValue = Objs0; } else { if (idx == group1maxIdx) { needValue = Objs1; } else { if (idx == group2maxIdx) { needValue = Objs2; } else { if (idx == group3maxIdx) { needValue = Objs3; } else { throw new Exception("意外值"); } } } } } else {//不是末級,要去下級找 if (idx <= group0maxIdx) {//決定進入Group0 if (Groups0 == null) { needValue = default(T); } else { needValue = Groups0.FindNeedValue(idx); } } else { if (idx <= group1maxIdx) {//決定進入Group1 if (Groups1 == null) { needValue = default(T); } else { needValue = Groups1.FindNeedValue(idx); } } else { if (idx <= group2maxIdx) {//決定進入Group2 if (Groups2 == null) { needValue = default(T); } else { needValue = Groups2.FindNeedValue(idx); } } else { if (idx <= group3maxIdx) {//決定進入Group3 if (Groups3 == null) { needValue = default(T); } else { needValue = Groups3.FindNeedValue(idx); } } else { throw new Exception("意外值"); } } } } } return needValue; } } public class Student { public string name; public int age; } } }
【原創】一個支持極限大小的數組MaxArray,且節省內存