为什么检查字典是否包含密钥更快,而不是捕获异常,以防万一它不? [英] Why is it faster to check if dictionary contains the key, rather than catch the exception in case it doesn't?

查看:132
本文介绍了为什么检查字典是否包含密钥更快,而不是捕获异常,以防万一它不?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下代码:

  public class obj 
{
// elided
}

public static Dictionary< string,obj> dict = new Dictionary< string,obj>();

方法1



public static obj FromDict1(string name)
{
if(dict.ContainsKey(name))
{
return dict [名称];
}
返回null;
}

方法2

  public static obj FromDict2(string name)
{
try
{
return dict [name];
}
catch(KeyNotFoundException)
{
return null;
}
}

如果性能有差异,我很好奇这两个功能,因为第一个应该是SLOWER比第二个 - 鉴于它需要检查两次,如果字典包含一个值,而第二个功能确实需要访问字典只有一次,但WOW,其实是相反的:



循环1 000 000个值(现有10万个和不存在90万个):


第一个功能:306毫秒



第二个功能:20483毫秒


为什么是这样?



编辑:正如你可以注意到这个问题下面的评论,第二个功能的表现实际上略好于第一个,如果有0个不存在键。但一旦存在至少一个或多个非现有密钥,第二个密钥的性能就会迅速下降。

解决方案

一方面,抛出异常本质上是昂贵的,因为堆栈必须是解除等等

另一方面,通过密钥访问字典中的值是便宜的,因为它是一个快速的O(1)操作。



BTW:正确的方法是使用 TryGetValue

  obj item; 
if(!dict.TryGetValue(name,out item))
return null;
返回项目;

这只访问一次,而不是两次。

如果你真的想要返回 null 如果该键不存在,则可以进一步简化上述代码:

  obj item; 
dict.TryGetValue(name,out item);
返回项目;

因为 TryGetValue 设置 item to null 如果没有名称的键存在。 >

Imagine the code:

public class obj
{
    // elided
}

public static Dictionary<string, obj> dict = new Dictionary<string, obj>();

Method 1

public static obj FromDict1(string name)
{
    if (dict.ContainsKey(name))
    {
        return dict[name];
    }
    return null;
}

Method 2

public static obj FromDict2(string name)
{
    try
    {
        return dict[name];
    }
    catch (KeyNotFoundException)
    {
        return null;
    }
}

I was curious if there is a difference in performance of these 2 functions, because the first one SHOULD be SLOWER than second one - given that it needs to check twice if the dictionary contains a value, while second function does need to access the dictionary only once but WOW, it's actually opposite:

Loop for 1 000 000 values (with 100 000 existing and 900 000 non existing):

first function: 306 milliseconds

second function: 20483 milliseconds

Why is that?

EDIT: As you can notice in comments below this question, the performance of second function is actually slightly better than first one in case there are 0 non existing keys. But once there is at least 1 or more non existing keys, the performance of second one decrease rapidly.

解决方案

On the one hand, throwing exceptions is inherently expensive, because the stack has to be unwound etc.
On the other hand, accessing a value in a dictionary by its key is cheap, because it's a fast, O(1) operation.

BTW: The correct way to do this is to use TryGetValue

obj item;
if(!dict.TryGetValue(name, out item))
    return null;
return item;

This accesses the dictionary only once instead of twice.
If you really want to just return null if the key doesn't exist, the above code can be simplified further:

obj item;
dict.TryGetValue(name, out item);
return item;

This works, because TryGetValue sets item to null if no key with name exists.

这篇关于为什么检查字典是否包含密钥更快,而不是捕获异常,以防万一它不?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆