字典与列表与数组的速度和功能

时间:2012-12-11 22:36:25

标签: c# .net list dictionary listbox

我正在使用.NET 4.5在C#中编写应用程序。我的应用程序读取和写入由硬件设备使用的二进制文件。该文件正好是5,000,000字节,由100,000个50字节“块”组成。每个50字节块将包含一个ASCII编码的字符串(可能只是一个空字符串)。设备需要文件布局,以便只需确定偏移量(索引* 50个字节然后读/写下50个字节)即可访问任何字符串。

我的WinForms应用程序需要能够:

  • 从文件中加载所有100,000个字符串并将其显示在UI(列表框)
  • 添加,编辑或删除字符串
  • 以正确的格式重写二进制文件

注意事项:

  1. 二进制文件中的大量数据最初将是空字符串,我不想向用户显示,但仍需要在我的数据结构中,以便我可以正确地重写文件。 / LI>
  2. 在添加新字符串之前,我需要确保有空闲空间(即至少有一个50字节的空白块)。如果没有,那么用户将需要“删除”现有字符串,以便为要添加的新字符串腾出空间。
  3. 在后台添加,修改和删除字符串的操作相同。添加只是将50个字节的空数据更改为50个字节的字符串数据,而删除则表示相反。
  4. 除了空字符串之外,不应存储重复的字符串,所以我需要一些方法来遍历我的数据结构,以确保在添加字符串或编辑字符串以匹配现有字符串之前字符串不存在
  5. 所以我需要一个数据结构来保存文件中的所有数据,我很难在字典,列表或数组之间做出决定。鉴于上面的警告,我不认为将任何数据结构直接绑定到UI是一个可行的解决方案。所以我认为我需要在该数据结构和列表框之间需要大量代码才能实现某种伪绑定。如果是这种情况,从功能的角度来看哪个数据结构(字典,列表,数组,其他)是最有用的,并提供最佳折衷方案:使用此大小的数据集(100,000个字符串,最多50个ASCII字符)的速度每个)?

4 个答案:

答案 0 :(得分:3)

如果性能至关重要,最好的解决方法就是测试它。编写一个快速而肮脏的应用程序,以三种方式执行关键任务,然后将其包装在一个循环中,完成10,000次,并查看哪个更快。

答案 1 :(得分:3)

字典在这里似乎没有必要,因为你没有任何密钥来索引你的数据 列表适用于添加/删除项目,但显然也不需要这样做 所以我会去一个字符串数组

编辑:重新考虑存在的多个空字符串,如果空字符串与填充字符串的比率不低,我可以建议可能的优化。
我们可以使用整数数组作为映射而不是仅包含填充字符串的字典

警告:需要测试

int[] keys = new int[100];  // Just 100 to test the idea
Dictionary<int, string> data = new Dictionary<int, string>();

AddItem(keys, 32, data, "Position 32 34567890123456789012345678901234567890");
AddItem(keys, 40, data, "Position 40 34567890123456789012345678901234567890");
AddItem(keys, 10, data, "Position 10 34567890123456789012345678901234567890");
AddItem(keys, 25, data, "Position 25 34567890123456789012345678901234567890");
AddItem(keys, 99, data, "Position 99 34567890123456789012345678901234567890");
AddItem(keys, 0, data, "Postion 00 234567890123456789012345678901234567890");
AddItem(keys, 18, data, "Position 18 34567890123456789012345678901234567890");

foreach(int x in keys)
{
    if(x == 0)
        Console.WriteLine("Empty string");
    else
        Console.WriteLine(data[x]);
}

void AddItem(int[] keys, int keyPos, Dictionary<int, string> data, string message)
{
    int count = data.Count;
    data.Add(count, message);
    keys[keyPos] = count;
}
void RemoveItem(int[] keys, int keyPos, Dictionary<int, string> data)
{
    int x = keys[keyPos];
    data.Remove(x);
    keys[keyPos] = 0;
}
void UpdateItem(int[] keys, int keyPos, Dictionary<int, string> data, string message)
{
    int x = keys[keyPos];
    data[x] = message;
}

答案 2 :(得分:1)

即使有100,000个条目,我也不认为你需要过多担心性能。 (编辑:我的意思是,当涉及到I / O或数据更改时的性能。您可能会遇到GUI绑定问题)

将其编程为最简单的方法,使您最容易对业务逻辑和GUI绑定进行更改。或许甚至可以考虑创建一个自己的类,只需用List(或Array或其他任何东西)包含GUI的标准公共接口来隐藏这个实现细节。

一旦您的GUI运行并且所有I / O运行正常(理想情况下,有一些不错的单元测试套件),那么您可以开始基准测试/分析并找到瓶颈所在。

编辑:考虑到您的要求,这个自定义/包装数据结构可能是理想的。它可以主动了解您数据的某些方面。例如,在加载/读取时,它可以检查新字符串是否有空间,因此当用户添加更多字符串时,您已经知道是否可以。它可以维护HashSet使用过的唯一字符串,因此您可以对重复的字符串进行很好的O(1)查找,依此类推。

答案 3 :(得分:0)

实际上,字典在这里最适合存储数据。关键是存储的字符串,值将是它的位置。您可以按字典的大小跟踪您的可用空间。

对于列表框,首先将字典转换为数组,然后使用该数组作为列表框的后备存储。这将是您在应用程序启动时支付的一次性速度惩罚,但是您可以通过UI响应获得更快的速度并满足底层数据存储的其他要求。

在字典上执行添加/删除操作,快速处理重复检查,如果更改基础字典而不是重建数组,则可以快速直接更新数组。