在C#,
的背景下最好的想法是什么在C#中我正在使用字典。我希望它使用更少的内存空间。什么会更好?
密钥类型为Uint64
或密钥类型为string
的字典?在这两种情况下,值都是一个自定义类,对于每个字典都是相同的。
我已将字典声明为以下内容,
private static readonly Dictionary<string, List<Node>> HashTable =
new Dictionary<string, List<Node>>();
类节点定义如下,
public class Node
{
public UInt64 CurrentIndex { get; set; }
public string NextHashedString { get; set; }
public int NextHashPos { get; set; }
}
字符串的键实际上是一个字符串的哈希值,计算如下, 字符串的长度可以是1到20个字符。
static UInt64 CalculateHash(string read, bool lowTolerance)
{
UInt64 hashedValue = 0;
int i = 0;
while (i < read.Length)
{
hashedValue += read.ElementAt(i) * (UInt64)Math.Pow(31, i);
if (lowTolerance) i += 2;
else i++;
}
return hashedValue;
}
现在,我想将此哈希值存储为字典的键。什么是最好的主意。我使用Uint64或我将其转换为字符串并使用字符串作为字典键。 我的主要目标是字典使用最小空间和密钥的搜索时间更快。
我有一个3571079个字符的文件。我可以将整个文件读成字符串还是需要高级数据结构?
答案 0 :(得分:3)
使用UInt64而不是字符串(或任何其他引用类型)作为字典的键实际上会消耗更少的内存。使用引用类型像字符串要求字典存储参照键,在它的内部数据结构,这将导致所引用的对象(字符串)要被保存在存储器中,以及,包括每个对象的开销等。当键是一个UInt64,(当前实现)字典存储键的值而不是对键的引用(作为泛型如何工作的正常方式的一部分),没有任何单独的键对象。
我只能想到一种情况,UInt64密钥可能会导致比字符串更高的内存使用量:如果进程是32位(x86)引用是32位。如果字典很大,但几乎为空,那么会有许多空的Dictionary<K,V>.Entry
实例。对于UInt64键,这些实例的关键部分将是64位(即使没有指定显式值),而对于字符串键,它只是32位。因此,对于具有UInt64键的字典,分配的内存总量将更多。但这是一个非常理论化的情况。
因此,如果您可以使用UInt64键而不是字符串而不牺牲软件设计的其他品质,那么使用它们并没有错。但是在真正需要之前不要开始优化。用Donald Knuth的话来说:“过早的优化是所有邪恶的根源”
更新:您已更新帖子以显示您的UInt64值的计算方式:
如果您只是通过在UInt64值上调用ToString来派生字符串键,那么您应该首先使用UInt64版本。一定会更有效率。
使用哈希作为密钥可能有些棘手。您需要确保散列不会发生碰撞。您的哈希函数在第一眼看上去并不是特别好,但这当然取决于您的用例。但是,我认为这超出了这个问题的范围。