【原创】一个支持极限大小的数组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;
        }

    }
}
时间: 2024-10-04 23:37:55

【原创】一个支持极限大小的数组MaxArray,且节省内存的相关文章

NET Framework 4.5新特性 (三)64位平台支持大于2 GB大小的数组

64位平台.NET Framework数组限制不能超过2GB大小.这种限制对于需要使用到大型矩阵和向量计算的工作人员来说,是一个非常大问题. 无论RAM容量有多大有多少,一旦你使用大型矩阵和向量计算工作的时候,经常会抛出一个System.OutOfMemoryException异常,如下图所示: 参考程序 class Program { private static void Main(string[] args) { int arrysize = 150000000; var large=ne

柔性数组(结构体最后一个域为0/1数组)

结构体最后的长度为0或1数组的作用(转载) 2012-05-07 17:07:09 其实很 早在看LINUX下就看到这个东西,后来在MFC内存池里同样也看到了类似的东西,还依照MFC写过一个类似的小内存池,(MFC用的是return this + 1)后来在李先静的<系统程序员成长计划>里看到了类似的定义,于是心里想着总结一下,结果发现网上已经有牛人总结的很好了,于是乎就转了过来,谢谢你们 的分享,这是我前进的动力!同时,需要引起注意的:ISO/IEC 9899-1999里面,这么写是非法的,

[经典面试题][谷歌]一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素

题目 一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素,要求O(1)空间和O(n)时间. 思路一 寻找重复元素,很容易想到建立哈希表来完成,遍历一遍数组就可以将每个元素映射到哈希表中.如果哈希表中已经存在这个元素则说明这就是个重复元素.这种方法可以很方便的在O(n)时间内完成对重复元素的查找.可是题目要求在O(1)的空间.因此采用哈希表这种解法肯定在空间复杂度上是不符合要求的.题目中数组中所以数字都在[0, n-1]区间范围内,因此哈希表的大小为n

交换两个相同大小的数组内容

     对于将两个相同大小的数组内容进行交换的问题,可以给出两个具体的算法,并给出相应的程序如下: 算法一分析:   将两个相同大小的数组内容进行交换,可以先定义两个相同大小的数组a[10]和b[10].同时,创建一个临时变量,借助这个变量,将两个数组的具体内容进行交换.下面是具体的程序: #include <stdio.h> int main() { int a[10]={1,2,3,4,5,6,7,8,9,0}; int b[10]={0,9,8,7,6,5,4,3,2,1}; int

不使用循环,如何创建一个长度为100的数组

前言: 问题描述:在不使用循环的条件下,如何创建一个长度为100的数组,并且数组的每一个元素是该元素的下标? 这是一个比较经典的前端面试题,也可以当笔试题,咋一看,好像难度不大,实际上考察的知识点还不少,值得写篇文章来备忘!废话不多说,直接进入正文! 正文: 为了理解这道题的意思,我们先用传统的方法来实现一下: 使用for方法: var arr = new Array(100); for(var i=0;i<arr.length;i++){ arr[i] = i; } console.log(a

一个能将给定非负整数数组中的数字排列成最大数字的函数

最近在网上看到这样一个题目,自己琢磨了一下. java version "1.8.0_40" // 编写一个能将给定非负整数数组中的数字排列成最大数字的函数. // 例如,给定[50,2,1,9],最大数字为95021. public class Sort { public static void main(String args[]){ int number[] = {1,2,3,32,335,34,7,6,9}; int number1[] = {312,321,3354,222,

python 开发一个支持多用户在线的FTP

### 作者介绍:* author:lzl### 博客地址:* http://www.cnblogs.com/lianzhilei/p/5813986.html### 功能实现 作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目录下文件 允许上传和下载文件,保证文件一致性 文件传输过程中显示进度条 附加功能

不使用sizeof求一个变量的大小

之前在腾讯实习生笔试的时候,遇到一个问题,当时一点思路也没有,现在想了想,找了一些资料,大体上明白了应该如何去做. 问题是: 使用C实现求一个变量的大小,不使用sizeof. 首先我先把我的代码贴上: #define size(x) ((char*)(&x+1)-(char*)(&x)) 该宏定义就实现了刚刚的需求. 首先,我们知道,char是占用一个字节的大小,我们得到一个变量之后,先取其引用,即&x,则该引用指向变量x的首地址. 而&x+1,是跨越该x之后的第一个地址.

Android 官方提供的支持屏幕大小的全部方法(精华)

本文将告诉你如何让你的应用程序支持各种不同屏幕大小,主要通过以下几种办法: 让你的布局能充分的自适应屏幕 根据屏幕的配置来加载合适的UI布局 确保正确的布局应用在正确的设备屏幕上 提供可以根据屏幕大小自动伸缩的图片 使用 "wrap_content" 和 "match_parent" 为了确保你的布局能够自适应各种不同屏幕大小,你应该在布局的视图中使用"wrap_content"和"match_parent"来确定它的宽和高.