1

在 C# 的上下文中最好的想法是什么,

  1. 在 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 或将其转换为字符串并将字符串用作字典键。我的主要目标是字典使用最少的空间并且搜索键的时间更快。

  2. 我有一个包含 3571079 个字符的文件。我可以将整个文件读入字符串还是需要高级数据结构?

4

1 回答 1

3

使用 UInt64 而不是字符串(或任何其他引用类型)作为字典的键实际上会消耗更少的内存。使用像字符串这样的引用类型需要字典在其内部数据结构中存储对键的引用,这将导致被引用的对象(字符串)也保存在内存中,包括每个对象的开销等。当键是 UInt64,(当前实现)字典存储键的值而不是对键的引用(作为泛型工作的正常方式的一部分),没有任何单独的键对象。

只有一种情况我能想到 UInt64 键可能导致比字符串更高的内存使用:如果进程是 32 位 (x86) 引用是 32 位的。如果字典很大,但几乎是空的,就会有很多空Dictionary<K,V>.Entry实例。对于 UInt64 键,这些实例的键部分将是 64 位(即使没有分配显式值),而对于字符串键,它只有 32 位。因此,对于具有 UInt64 键的字典,分配的内存总量将更多。但这是一个非常理论的情况。

因此,如果您可以使用 UInt64 键而不是字符串而不牺牲软件设计的其他品质,那么使用它们没有任何问题。但是在真正需要之前不要开始优化。用 Donald Knuth 的话来说:“过早的优化是万恶之源”

更新:当您更新帖子以显示您的 UInt64 值的计算方式时:

  1. 如果您只是通过在 UInt64 值上调用 ToString 来派生字符串键,您应该首先选择 UInt64 版本。无论如何都会更有效率。

  2. 使用散列作为键可能有点棘手。您需要确保哈希不会发生冲突。您的哈希函数乍一看并不是特别好,但这当然取决于您的用例。但这超出了我想的这个问题的范围。

于 2012-03-03T10:55:56.210 回答