C# 优化字典键的内存需求

C# 优化字典键的内存需求,c#,.net,collections,C#,.net,Collections,除此之外,我还有一个字典实例的(大)集合。该字典中的键值始终是10个已知字符串中的一个 如果集合包含1000000个条目,则该字符串键值是否会占用每个实例和键的内存?有没有什么好的方法来优化这样的案例,比如使用字符串内部处理 另一种方法是使用say a short代替键,并在字符串和short之间进行转换,但语法get有点混乱…通常不是-它们存储为单个不可变变量。可以使用字符串,这将有助于节省内存 但这要视情况而定。如果每次构造字符串(例如串联),它们将不会被插入。将它们定义为常量可确保它们将被

除此之外,我还有一个字典实例的(大)集合。该字典中的键值始终是10个已知字符串中的一个

如果集合包含1000000个条目,则该字符串键值是否会占用每个实例和键的内存?有没有什么好的方法来优化这样的案例,比如使用字符串内部处理


另一种方法是使用say a short代替键,并在字符串和short之间进行转换,但语法get有点混乱…

通常不是-它们存储为单个不可变变量。可以使用字符串,这将有助于节省内存

但这要视情况而定。如果每次构造字符串(例如串联),它们将不会被插入。将它们定义为常量可确保它们将被拘留


您可以使用
object.ReferenceEquals()
检查内存中的两个字符串是否相同。我认为为了节省空间或优化它,我们可以执行以下操作之一

  • 为每个项目名称(字符串)创建10个不同的整数。然后在检索时在所有10个列表中搜索项目

  • 或者像这样创建一个列表字典,并为每个项目名称(字符串)存储每个键(在各自的列表中)。它几乎和上面一样,但允许您在将来添加更多项目

我相信我们仍然会有更好的表现

(但我希望其他人对我的假设发表评论)


另外,如果您有大约100000条记录,最好将其存储在数据库中,并有两个表,其中一个表包含字符串和项目名称的ID,另一个表包含项目ID的键和外键。

字符串是一种引用类型。字典包含对实际字符串对象的引用,在32位操作系统上为4字节。将同一字符串添加到多个词典只会生成该字符串的一个副本


你已经找到了你要找的东西。

常量字符串被实习(因此
string str=“hello”
被实习)。其他字符串通常不是。您可以使用
string.Intern
static方法强制插入字符串,但一定要阅读上的副作用。请记住,如果您有一个const
hello
字符串和一个动态构建的
hello
字符串,则只有第一个字符串将被插入。有时,通过插入常用字符串可以获得一点内存。
在您的情况下,如果您只使用少量已存储在另一个集合中的字符串,并复制这些字符串(
var str2=str1
),那么您不是在复制该字符串,而是在创建另一个引用。但是,如果您通过操作旧字符串(
var str2=(“Z”+str1).Substring(1)
)获得新字符串,那么您实际上是在创建一个新字符串,而不是引用旧字符串。

正如其他人所说,这取决于如何将字符串放入列表中。几个例子应该会有所帮助

假设您有一个包含1000行的文本文件,所有这些都是一样的。也就是说,一个文件的“hello”重复了1000次:

hello
hello
hello
...
如果您编写一个程序,以简单的方式将该文件读入
列表
,那么将有1000个不同的字符串实例。即:

var myList = new List<string>();
var reader = new StreamReader("filename");
string s;
while ((s = reader.ReadLine()) != null)
{
    myList.Add(s);  // each string is a unique instance
}
在这种情况下,程序中只有一个字符串实例
“hello”

您可以对列表中的键执行类似的操作。为键创建查找表,并确保无论何时向列表中添加键,都是从查找表中添加值,而不是键本身


正如其他人所指出的,如果已知键已经是常量,并且在将它们添加到列表中时始终使用常量值,则字符串已经被保留,并且不需要上述内容。

如果您的字符串始终是10且众所周知的,为什么不使用
enum
?字典中不能有多个相同的键。你是说10个字符串代表值吗?它们是相同的,但不是静态的,即有一个包含所有有效字段名称的动态定义常量字符串被插入。这就是我所说的“将这些定义为常量将确保它们将被拘留。”
var KeyLookup = new Dictionary<string, string>();
string AddString(string key)
{
    string value;
    if (!KeyLookup.TryGetValue(key, out value))
    {
        value = key;
        KeyLookup.Add(key, value);
    }
    return value;
}
while ((s = reader.ReadLine()) != null)
{
    myList.Add(AddString(s));  // duplicate strings use the same instance
}