CSharp中的集合与字典:不同数据量的内存占用情况

1. CSharp中的集合

        集合(Collection)类是专门用于数据存储和检索的类。这些类提供了对栈(stack)、队列(queue)、列表(list)和哈希表(hash table)的支持。大多数集合类实现了相同的接口。

        集合(Collection)类服务于不同的目的,如为元素动态分配内存,基于索引访问列表项等等。这些类创建 Object 类的对象的集合。在 C# 中,Object 类是所有数据类型的基类。

1.1. 各种集合类

1.1.1. 动态数组(ArrayList)

  • 它代表了可被单独索引的对象的有序集合。

  • 它基本上可以替代一个数组。但是,与数组不同的是,您可以使用索引在指定的位置添加和移除项目,动态数组会自动重新调整它的大小。它也允许在列表中进行动态内存分配、增加、搜索、排序各项。

1.1.2. 哈希表(Hashtable)

  • 它使用键来访问集合中的元素。

  • 当您使用键访问元素时,则使用哈希表,而且您可以识别一个有用的键值。哈希表中的每一项都有一个键/值对。键用于访问集合中的项目。

1.1.3. 排序列表(SortedList)

  • 它可以使用键和索引来访问列表中的项。

  • 排序列表是数组和哈希表的组合。它包含一个可使用键或索引访问各项的列表。如果您使用索引访问各项,则它是一个动态数组(ArrayList),如果您使用键访问各项,则它是一个哈希表(Hashtable)。集合中的各项总是按键值排序。

1.1.4. 堆栈(Stack)

  • 它代表了一个后进先出的对象集合。

  • 当您需要对各项进行后进先出的访问时,则使用堆栈。当您在列表中添加一项,称为推入元素,当您从列表中移除一项时,称为弹出元素。

1.1.5. 队列(Queue)

  • 它代表了一个先进先出的对象集合。

  • 当您需要对各项进行先进先出的访问时,则使用队列。当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队。

1.1.6. 点阵列(BitArray)

  • 它代表了一个使用值 1 和 0 来表示的二进制数组。

  • 当您需要存储位,但是事先不知道位数时,则使用点阵列。您可以使用整型索引从点阵列集合中访问各项,索引从零开始。

1.2. 泛型集合List

        集合是OOP中的一个重要概念,C#中对集合的全面支持更是该语言的精华之一。

1.3. 为什么要用泛型集合?

        在C# 2.0之前,主要可以通过两种方式实现集合:

  1. 使用ArrayList

        直接将对象放入ArrayList,操作直观,但由于集合中的项是Object类型,因此每次使用都必须进行繁琐的类型转换。

  1. 使用自定义集合类

        比较常见的做法是从CollectionBase抽象类继承一个自定义类,通过对IList对象进行封装实现强类型集合。这种方式要求为每种集合类型写一个相应的自定义类,工作量较大。泛型集合的出现较好的解决了上述问题,只需一行代码便能创建指定类型的集合。

string strPrefix = txtPrefix.Text;

int count = Convert.ToInt32(txtNumCount.Text);

List<string> listData= new List<string>();

for (int i = 0; i < count; i++)
{
    listData.Add(strPrefix + i);
}

int count = Convert.ToInt32(txtNumCount.Text);

List<int> listData = new List<int>();

for (int i = 0; i < count; i++)
{
    listData.Add(i);
}
List<Person> listData = new List<Person>();
listData.Add(new Person("张三",17));
listData.Add(new Person("李四",18));
listData.Add(new Person("王五",19));

class Person
{
    private string _name; //姓名
    private int _age; //年龄
    //创建Person对象
    public Person(string Name, int Age)
    {
        this._name= Name;
        this._age = Age;
    }
    //姓名
    public string Name
    {
        get { return _name; }
    }
    //年龄
    public int Age
    {
        get { return _age; }
    }
}

2. CSharp中的字典

2.1. Dictionary

  • 必须包含名空间System.Collection.Generic
  • Dictionary里面的每一个元素都是一个键值对(由二个元素组成:键和值)
  • 键必须是唯一的,而值不需要唯一的
  • 键和值都可以是任何类型(比如:string, int, 自定义类型,等等)
  • 通过一个键读取一个值的时间是接近O(1)
  • 键值对之间的偏序可以不定义
string strPrefix = txtPrefix.Text;
int count = Convert.ToInt32(txtNumCount.Text);

Dictionary<string,bool> dicData = new Dictionary<string,bool>();

for (int i = 0; i < count; i++)
{
    dicData.Add(strPrefix + i,true);
}
int count = Convert.ToInt32(txtNumCount.Text);

Dictionary<int, bool> dicData = new Dictionary<int, bool();

for (int i = 0; i < count; i++)
{
    dicData.Add(i, true);
}
//定义
Dictionary<string, string> openWith = new Dictionary<string,string>();
//添加元素
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe");

3.CSharp中泛型集合与字典的内存使用情况

我们现在建立两组数据,向List<string> listDataDictionary<string,bool> dicDataList<int> listDataDictionary<int, bool> dicData 4个集合中添加数据


private void btnAutomaticMemory_Click(object sender,EventArgs e)
{
    string strPrefixInfo = txtPrefix.Text;
    Console.WriteLine("********************************************************************");
    Console.WriteLine($"字符串为【{strPrefixInfo}】");
    Console.WriteLine("********************************************************************");
    AlterPrefixAndNumCount(strPrefixInfo, 10);
    AutomaticMemory(10);
    AlterPrefixAndNumCount(strPrefixInfo, 100);
    AutomaticMemory(100);
    AlterPrefixAndNumCount(strPrefixInfo, 1000);
    AutomaticMemory(1000);
    AlterPrefixAndNumCount(strPrefixInfo, 10000);
    AutomaticMemory(10000);
    AlterPrefixAndNumCount(strPrefixInfo, 20000);
    AutomaticMemory(20000);
    AlterPrefixAndNumCount(strPrefixInfo, 50000);
    AutomaticMemory(50000);
    AlterPrefixAndNumCount(strPrefixInfo, 100000);
    AutomaticMemory(100000);
    AlterPrefixAndNumCount(strPrefixInfo, 200000);
    AutomaticMemory(200000);
    AlterPrefixAndNumCount(strPrefixInfo, 500000);
    AutomaticMemory(500000);
    AlterPrefixAndNumCount(strPrefixInfo, 1000000);
    AutomaticMemory(1000000);
    AlterPrefixAndNumCount(strPrefixInfo, 2000000);
    AutomaticMemory(2000000);
    AlterPrefixAndNumCount(strPrefixInfo, 5000000);
    AutomaticMemory(5000000);
    AlterPrefixAndNumCount(strPrefixInfo, 10000000);
    AutomaticMemory(10000000);
    AlterPrefixAndNumCount(strPrefixInfo, 20000000);
    AutomaticMemory(20000000);
}
private void AutomaticMemory(int numCount)
{
    Console.Write($"| {numCount} |");
    btnLoadListStringData_Click(null, null);
    btnLoadDictionaryStringData_Click(null, null);
    btnLoadListIntData_Click(null, null);
    btnLoadDictionaryIntData_Click(null, null);
    Console.WriteLine("");
}

/// <summary>
/// 加载集合数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnLoadListStringData_Click(object sender, EventArgs e)
{
    string strPrefix = txtPrefix.Text;

    int count = Convert.ToInt32(txtNumCount.Text);

    List<string> listData= new List<string>();

    for (int i = 0; i < count; i++)
    {
        listData.Add(strPrefix + i);
    }
    
    ShowProcessInfoTabel();
}

private void btnLoadDictionaryStringData_Click(object sender, EventArgs e)
{
    string strPrefix = txtPrefix.Text;

    int count = Convert.ToInt32(txtNumCount.Text);

    Dictionary<string,bool> dicData = new Dictionary<string, bool>();

    for (int i = 0; i < count; i++)
    {
        dicData.Add(strPrefix + i,true);
    }
    
    ShowProcessInfoTabel();
}

private void btnLoadListIntData_Click(object sender, EventArgs e)
{
    int count = Convert.ToInt32(txtNumCount.Text);

    List<int> listData = new List<int>();

    for (int i = 0; i < count; i++)
    {
        listData.Add(i);
    }
    
    ShowProcessInfoTabel();
}

private void btnLoadDictionaryIntData_Click(object sender, EventArgs e)
{
    int count = Convert.ToInt32(txtNumCount.Text);

    Dictionary<int, bool> dicData = new Dictionary<int, bool>();

    for (int i = 0; i < count; i++)
    {
        dicData.Add(i, true);
    }
    
    ShowProcessInfoTabel();
}

/// <summary>
/// 显示程序的内存占用信息
/// </summary>
/// <param name="strPhaseInfo"></param>
public void ShowProcessInfoTabel()
{
    //实时分析内存至关重要
    GC.Collect();

    var name = Process.GetCurrentProcess().ProcessName;
    PerformanceCounter curpcp = new PerformanceCounter("Process", "Working Set - Private", name);
    PerformanceCounter curtime = new PerformanceCounter("Process", "% Processor Time", name);
    Console.Write($"   {curpcp.NextValue() / MB_DIV}  |");
    Application.DoEvents();
}

3.1. 连续数字集合内存占用

个数连续数字集合内存占用MB连续数字字典内存占用MB
108.906258.945313
1008.9453138.945313
10008.9453138.945313
1000010.0156310.42188
2000011.8671912.58203
5000014.5820316.59766
10000015.5664119.82422
20000016.8320325.68359
50000018.6757824.97266
100000022.8085935.58984
200000022.8359456.76563
500000035.17188115.2852
1000000055.85156216.0703

3.2. 字符串集合内存占用:君子慎独,不欺暗室。 卑以自牧,含章可贞。

个数集合内存占用MB字典内存占用MB
1010.476568.78125
1008.9453138.945313
10008.9453138.945313
100009.37510.53516
2000010.5703112.83203
5000013.3671919.13672
10000015.8437527.03125
20000029.4492240.51953
50000050.5273460.5
100000086.64063105.9297
2000000155.6563203.5977
5000000391.207474.2734
10000000771.125936.5156

3.2. 字符串集合内存占用:臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。

个数集合内存占用MB字典内存占用MB
1010.585948.902344
1009.06259.0625
10009.06259.0625
1000011.0976614.29688
2000014.1835919.70313
5000019.7527.85547
10000035.8710942.65234
20000054.3242271.60547
500000127.8242137.7461
1000000242.6445262.5938
2000000464.4609514.0898
50000001146.6251235.301
100000002291.0862459.48
********************************************************************
字符串为【君子慎独,不欺暗室。 卑以自牧,含章可贞。】
********************************************************************
| 10 |   10.47656  |   8.78125  |   8.90625  |   8.945313  |
| 100 |   8.945313  |   8.945313  |   8.945313  |   8.945313  |
| 1000 |   8.945313  |   8.945313  |   8.945313  |   8.945313  |
| 10000 |   9.375  |   10.53516  |   10.01563  |   10.42188  |
| 20000 |   10.57031  |   12.83203  |   11.86719  |   12.58203  |
| 50000 |   13.36719  |   19.13672  |   14.58203  |   16.59766  |
| 100000 |   15.84375  |   27.03125  |   15.56641  |   19.82422  |
| 200000 |   29.44922  |   40.51953  |   16.83203  |   25.68359  |
| 500000 |   50.52734  |   60.5  |   18.67578  |   24.97266  |
| 1000000 |   86.64063  |   105.9297  |   22.80859  |   35.58984  |
| 2000000 |   155.6563  |   203.5977  |   22.83594  |   56.76563  |
| 5000000 |   391.207  |   474.2734  |   35.17188  |   115.2852  |
| 10000000 |   771.125  |   936.5156  |   55.85156  |   216.0703  |


********************************************************************
字符串为【臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。】
********************************************************************
| 10 |   10.58594  |   8.902344  |   9.027344  |   9.0625  |
| 100 |   9.0625  |   9.0625  |   9.0625  |   9.0625  |
| 1000 |   9.0625  |   9.0625  |   9.0625  |   9.0625  |
| 10000 |   11.09766  |   14.29688  |   13.77734  |   14.18359  |
| 20000 |   14.18359  |   19.70313  |   14.42578  |   15.14063  |
| 50000 |   19.75  |   27.85547  |   14.89844  |   16.91016  |
| 100000 |   35.87109  |   42.65234  |   15.58984  |   19.85156  |
| 200000 |   54.32422  |   71.60547  |   17.05859  |   25.91016  |
| 500000 |   127.8242  |   137.7461  |   18.94531  |   25.24219  |
| 1000000 |   242.6445  |   262.5938  |   23.42969  |   36.21094  |
| 2000000 |   464.4609  |   514.0898  |   24.39063  |   58.32031  |
| 5000000 |   1146.625  |   1235.301  |   38.19141  |   118.3047  |
| 10000000 |   2291.086  |   2459.48  |   61.78516  |   222.0898  |
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自己的九又四分之三站台

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值