【问题标题】:Insert into a generic dictionary with possibility of duplicate keys?插入可能存在重复键的通用字典?
【发布时间】:2010-04-02 15:33:29
【问题描述】:

当插入到可能发生键冲突的通用字典中时,是否有任何理由偏爱其中一种方法而不是另一种方法?我正在构建静态集合的内存版本,因此在发生冲突的情况下,使用旧值还是新值都没有关系。

If Not mySettings.ContainsKey(key) Then
    mySettings.Add(key, Value)
End If

对比

mySettings(key) = Value

当然还有这个,这显然不是正确的做法:

Try
    mySettings.Add(key, Value)
Catch
End Try

很明显,这里最大的区别是第一种方法和第二种方法实际上做不同的事情,但在我的情况下这并不重要。第二种方法似乎更干净,但我很好奇你们中的任何.net 大师是否有更深入的见解。谢谢!

【问题讨论】:

  • @Patrick:这是 VB.net,而不是 C#
  • 噢!对不起。好吧,标签更改会吸引流量。 . .

标签: .net vb.net generics


【解决方案1】:

假设你说替换与否无关紧要,我们希望真的挑剔:

选项 1 的优势:

  • 它更清楚地表明了密钥重复是预期的并且可以的。
  • 虽然微不足道,但在有很多重复项的情况下应该稍微快一些,因为它通常可以避免不必要的分配。这种性能差异非常小,即使通过测试也很难感知..

选项 2 的优势:

  • 节省了代码行数,尽管在大多数情况下这并不是一个很大的优势。如果代码位于某个紧凑的位置(例如语句 lambda 或其他内容),则很有帮助。

除非需要更严格的代码,否则我会选择选项 1。我猜。两者都可以。

编辑:在下面的 cmets 中讨论并考虑更多之后,我认为选项 2通常会更快。只有当有非常小的一组值非常大量的重复时,选项 1 可能会更快。

【讨论】:

  • 我不确定效率差异。第一个选项对字典进行两次搜索(在新值的情况下),而第二个(可能)只进行一次。我认为必须对它进行基准测试才能找到任何性能差异。但正如你所说,无论如何,差异都是微不足道的。
  • 对。我确实指定了如果有很多重复项。如果不是,那么选项 2 的 always-assign 将不会是一个缺点,并且选项 1 将进行双重查找(即使非常有效)并无论如何分配。所以,视情况而定。尽管正如我们所同意的那样,两者的区别都是微不足道的。
  • 仅供参考 - 选项 2 通常会更快。 Contains() 检查与选项 2 使用的内部代码几乎相同(除了单值分配)。在选项 1 中,您正在执行 2x 的检查(因为 add 再次执行此操作),因此几乎每个调用都需要重复才能弥补性能。单个赋值的区别...
  • 我确实同意您的第一个陈述(尽管只是勉强同意,因为使用 Item[] 也表明了这一点)-但另一个选项确实不正确。
【解决方案2】:

如果您不在乎在发生冲突的情况下使用哪个元素,我个人会赞成:

mySettings(key) = Value

这将导致mySettings 包含新元素,因为Item 将替换现有元素。

如果您希望保留旧值,那么您的第一个选项是最好的,因为它不会 Add 除非密钥是唯一的。

If Not mySettings.ContainsKey(key) Then
    mySettings.Add(key, Value)
End If

此行为与上述选项不同 - 主要是因为 old 值将保留在指定 key 的字典中。

我不会使用第三个选项 - 它将提供与上面的 ContainsKey 选项相同的行为,但由于(非显而易见的)异常处理而增加了开销。

【讨论】:

    【解决方案3】:

    我同意,由于您不在乎获得哪个值,因此所有三个都可以完成工作,尽管它们做的事情不同(第一个和第三个保持原始值,而第二个始终获得最新值)。

    我也同意第二个是最干净的,第三个是一个坏主意,因为它依赖于异常情况下的异常。

    【讨论】:

      【解决方案4】:

      因为选项 1 和 2 做不同的事情,所以哪个最合适将取决于您的情况。

      例如,我有一个线程安全的字典类,用于缓存本质上可互换的不可变项。在这种情况下,我重写了 Add 方法以使用您的选项 2(当然受到适当同步的保护)。这意味着多个线程可以在没有竞争条件的情况下添加项目,并具有“最后更新获胜”语义。

      另一方面,如果字典存储可变项,选项 1 可能是必不可少的,因为您不希望默默地覆盖现有项。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-17
        • 2014-07-22
        • 1970-01-01
        • 1970-01-01
        • 2017-07-18
        • 2014-08-21
        • 1970-01-01
        相关资源
        最近更新 更多