2

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

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

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

谢谢!

4

5 回答 5

7

是的。

O(1)简单地说,无论有多少项目,操作都需要相同的时间。
并不意味着它所花费的时间与简单地访问局部变量一样快。

此外,请考虑以下事项:

  1. 访问局部变量更具可读性
  2. TryGetValue通常,您希望在通过键访问字典中的值时进行错误处理甚至使用。使用局部变量时,您可以将此代码保存在一个地方,而不必将其涂抹在整个方法中。
于 2012-08-29T07:41:10.987 回答
3

是的:

  • 它避免了耗时的多次 O(1) 查找
  • 它比dictionary["key"]每次写都更具可读性
于 2012-08-29T07:41:44.357 回答
1

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

  • 字典并不是真正的 O(1)。数据在内部被划分为小集合,字典通过哈希码知道要在哪个集合中搜索。尽管如此,还是涉及到一个内部集合枚举,因此该操作不是免费的(虽然不贵)

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

于 2012-08-29T07:43:07.830 回答
1

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

这是一个小优化,但并非每个小优化都是过早的。确实会节省时间。

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

也许不是手头的案例,但就什么是良好实践而言,我们必须考虑比手头的案例更广泛的案例——使某些东西成为“良好实践”的部分原因在于它涵盖了大量具有类似只有当我们知道我们为什么这样做时,我们才会离开的代码。

没有线程,我们的原因是:

  1. 我们以相同的结果重复使用相同的代码。
  2. 编译器不太可能意识到这一点并为我们重写一次调用。
  3. 它可以增加可读性。

最后一点值得考虑。变量的每次命名都是使代码自我记录的机会。发生了什么更清楚:

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. 否则,它消除了来自线程的许多风险,因为我们正在处理本地并且知道它将始终是相同的本地。

因此,虽然一些线程案例缓解了这种方法,而且很多人坚持使用它,它不再是一种优化,而是正确性所必需的。

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

所以,虽然在这里并不重要,但它仍然是它通常是良好实践的一个原因。

于 2012-08-29T08:13:29.663 回答
0

是的...

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

于 2012-08-29T07:43:36.970 回答