在多次使用时存储O(1)哈希集查找的结果是一个好习惯吗?

时间:2012-08-29 07:39:44

标签: c# .net performance design-patterns dictionary

我使用哈希集结构进行映射:Dictionary<string, string>

如果我需要在连续语句中多次读取myHashset [“key1”]的值,那么使用局部变量存储第一个查找是一个好习惯吗?

编辑:没有其他线程可以修改字典,因此它不是一个重要的标准。

谢谢!

5 个答案:

答案 0 :(得分:8)

是。

O(1)只是声明操作需要相同的时间,无论有多少项目 意味着,它所花费的时间与访问本地变量的速度一样快。

此外,请考虑以下事项:

  1. 访问本地变量更具可读性
  2. 通常,您希望在通过键访问字典中的值时进行错误处理甚至使用TryGetValue。使用局部变量时,您可以将此代码保存在一个位置,而不必在整个方法中涂抹它。

答案 1 :(得分:4)

是:

  • 它避免了多次耗时的O(1)查找
  • 它比每次写dictionary["key"]更具可读性

答案 2 :(得分:1)

这是一个很好的做法,至少有两个原因:

  • 字典不是真正的O(1)。数据在内部划分为小集合,并且由于哈希码,字典知道要搜索哪个集合。但是,还有一个内部集合枚举,因此操作不是免费的(虽然不贵)

  • 可以从另一个线程修改该值。保留引用有助于使代码在线程安全并防止意外结果。

答案 3 :(得分:1)

执行O(1)次操作n次是O(n)!

这是一个小的优化,但不是每一次小优化都是不成熟的。这确实可以节省时间。

  

编辑:没有其他线程会修改字典,所以它不是一个重要的标准。

也许不是手头的情况,但就什么是好的做法而言,我们必须考虑更广泛的案例,而不仅仅是手头的案例 - 使“良好实践”的一部分是它覆盖了大量的具有类似代码的情况,只有当我们知道为什么会这样做时才会离开。

没有线程,我们的理由是:

  1. 我们用相同的结果反复敲击相同的代码。
  2. 编译器不太可能意识到这一点并重写为我们的单个调用。
  3. 它可以提高可读性。
  4. 最后一点值得考虑。变量的每个命名都是使代码自我记录的机会。哪个更清楚:

    CheckUpdated(dict[passedValue.split('\t')[1].Trim().ToUpperInvariant()]);
    MarkLastCheckTime(dict[passedValue.split('\t')[1].Trim().ToUpperInvariant()]);
    return GetStatus(dict[passedValue.split('\t')[1].Trim().ToUpperInvariant()];
    

    或者:

    var purchaseOrderCode = dict[passedValue.split('\t')[1].Trim().ToUpperInvariant()];
    CheckUpdated(purchaseOrderCode);
    MarkLastCheckTime(purchaseOrderCode);
    return GetStatus(purchaseOrderCode);
    

    在第一种情况下,我有点故意隐晦,即使我不断使用相同的字典,我也应该只做一次这样的工作,但实际代码中的影响较小,因为它是一个源文件充满了真实的代码而不是四行的例子。

    使用线程,它变成了一个问题:

    1. 如果我们需要与可能的更改交错,我们就无法做到这一点。
    2. 否则,它会消除线程带来的很多风险,因为我们正在为当地人工作并且知道它将在整个地方都是一样的。
    3. 因此,虽然有些线程案例可以缓解这种方法,并且很多人坚持这种方法,但它不再是优化,而是正确性所必需的。

      知道我们处于哪种情况并考虑其他线程确实变得更加复杂 - 因为在某些情况下我们确实希望在另一个线程更新字典时允许有问题的对象发生变化。但大多数情况下,我们确实希望在面对来自其他线程的更改时继续处理相同的对象。

      所以,虽然这里不重要,但它仍然是一般的良好做法的原因。

答案 4 :(得分:0)

是的...

你自己有答案。它将有助于节省微秒和CPU周期。 :)