我有一个标志字典,每个事件都设置了相关的标志。某些事件来自相同类型且具有相同的ID,因此可以多次设置其标志。如果我在设置之前检查一个标志会更快吗?
Dictionary<int, bool> flags = new Dictionary<string, bool>();
foreach(var eventType in eventTypes)
{
flags.Add(eventType.id, false);
}
for (int i = 0; i < iterations; i++)
{
// resetting flags for current iteration.
foreach(var k in flags.Keys)
{
flags[k] = false;
}
Event[] events = GetEvents();
foreach(var e in events)
{
flags[e.id] = True; // Would it be better to check flag before set it?
}
// Do related works for events occurred
}
答案 0 :(得分:2)
在这种情况下,当您索引字典时,会发生最昂贵的操作。每当您尝试添加,更新或读取特定密钥的值时,Dictionary
需要计算密钥的哈希值,然后获取相应的桶,然后遍历该桶中的元素(如果有更多而不是一个哈希冲突)并将它们与密钥进行比较。
如果您在更新之前检查了该值,则需要执行此操作两次,以防您需要更改该值。
在旁注中,这正是为什么TryGetValue
是获取值可能在字典中或不在字典中的首选(更高性能)方法的原因:因为调用ContainsKey
然后索引字典将需要两个操作(或者更糟糕的是,捕获KeyNotFoundException
)。
此外,如果int
键的范围有限,您可以考虑使用BitArray
代替Dictionary
。
<强> [编辑] 强>
据推测,您可以使用字典来检查给定事件是否至少发生过一次。要做到这一点,你可以简单地写:
var eventIds = new HashSet<string>(GetEvents().Select(e => e.Id));
要检查事件是否有效发生,您将查询hashset:
if (eventIds.Contains(id))
{
// do something
}
答案 1 :(得分:2)
在任何基于字典的操作中,查找时间可能远远超过设置标志所需的时间,这通常只涉及在内存中设置单个值。
如果你只是设置了标志而没有检查,那么只涉及一次查找。
如果先检查,则可能涉及两次查找。但是,编译器很可能会将其优化为单个查找,因此速度可能相似。
结论:
不检查可能更快,但只有在编译器不擅长优化时才会发现这一点
如果您真的关心性能,请考虑是否可以在应用程序中使用数组而不是字典,因为数组往往更快。
然而,这只是基于我的知识和直觉。如果您对性能非常认真,那么唯一真正的解决方案就是编写一些代码来测试各种方法的速度!
答案 2 :(得分:1)
如果标记为false
,则仅将标记设置为true
较慢,因为您需要两次查询字典。
如果直接设置标志,则只有一个操作。
另外,如果你有一个多线程环境,你还需要防止竞争条件。在&#34;检查和设置&#34;周围加lock
逻辑会减慢它的速度。
进行检查的唯一原因我能想到的是,如果你有一个自定义字典,它会在set事件上触发某些事情,即使它是相同的值并且你想避免这种情况。