我最近在我的公司看到了一个新趋势,我们通过简单的LINQ转换将IEnumerable更改为字典,如下所示:
enumerable.ToDictionary(x=>x);
当集合上的操作是包含/访问时,我们大多数情况下都会这样做,显然字典在这种情况下具有更好的性能。
但是我意识到将Enumerable转换为字典有其自身的成本,我想知道它在什么时候开始收支平衡(如果确实如此),即 IEnumerable
的性能包含/访问权限等于ToDictionary
+访问/包含。
好的我可能会补充说没有数据库访问可以从数据库查询中创建枚举,就是这样,可以在之后编辑枚举...
知道密钥的数据类型如何影响性能会很有趣吗?
查询可能一般是2-5次,但有时也可能是一次。但我见过像这样的东西 对于可枚举的:
var element=Enumerable.SingleorDefault(x=>x.Id);
//do something if element is null or return
获取字典:
if(dictionary.ContainsKey(x))
//do something if false else return
这已经困扰了我很长一段时间了。
答案 0 :(得分:7)
字典与IEnumerable相比的性能
正确使用时,Dictionary
总是更快读取(除非数据集非常小,例如10项)。创建它时可能会有开销。
给定m
作为针对同一对象执行的查找量(这些是近似值):
IEnumerable
的性能(从干净列表中创建):O(mn)
m * O(n)
)。Dictionary
的效果:O(n) + O(1m)
或O(m + n)
O(n)
)。通常可以看出Dictionary
在m > 1
时获胜,而IEnumerable
在m = 1
或m = 0
时获胜。
一般来说,你应该:
Dictionary
。IEnumerable
。IEnumerable
。
Dictionary
一样使用,因此您可以使用它来抵消内存压力。进一步考虑
Dictionary
使用GetHashCode()
来组织其内部状态。 Dictionary
的性能以两种方式与哈希码密切相关。
GetHashCode()
- 每次添加,查找或删除项目时都会产生开销。O(1)
查找性能。大多数内置.Net类型(尤其是值类型)都有非常好的散列算法。但是,类似列表的类型(例如字符串)GetHashCode()
具有O(n)
性能 - 因为它需要遍历整个字符串。因此,字典的性能可以被视为(M
对于高效GetHashCode()
来说是最好的哦:O(1) + M
。
答案 1 :(得分:2)
这取决于....
IEnumerable有多长?
访问IEnumerable会导致数据库访问吗?
多久访问一次?
最好的办法是进行实验和剖析。
答案 2 :(得分:1)
如果您经常通过某个键搜索集合中的元素 - 定义字典会更快,因为或者基于散列的集合和搜索时间更快,否则如果您不通过集合搜索很多 - 转换不是必需的,因为转换的时间可能比您在集合中的一两次搜索更大,
答案 3 :(得分:0)
恕我直言:您需要使用具有代表性的数据在您的环境中进行测量。在这种情况下,我只需编写一个快速控制台应用程序来衡量代码执行的时间。为了获得更好的衡量标准,我需要多次执行相同的代码。
ADD:
它还取决于您开发的应用程序。通常,您会在这个时间和精力上获得更多优化其他地方(避免网络环境,缓存等)。
答案 4 :(得分:0)
我要补充一点,你没有告诉我们每次你“回放”IEnumerable<>
时会发生什么。它是否直接由数据收集支持? (例如List<>
)还是“动态”计算?如果它是第一个,对于小集合,枚举它们以找到想要的元素更快(3/4元素的字典是没用的。如果你想我可以建立一些基准来找到断点)。如果它是第二个,那么你必须考虑是否“缓存”集合中的IEnumerable<>
是个好主意。如果是,那么您可以选择List<>
或Dictionary<>
,然后返回到第1点。IEnumerable
是小还是大?还有第三个问题:如果集合没有备份,但它对于内存来说太大了,那么显然你不能把它放在Dictionary<>
中。那么也许是时候让SQL为你工作了: - )
我会补充说“失败”会产生费用:如果你试图找到一个不存在的元素,则在List<>
中,费用为O(n)
,而在{{1}费用仍为Dictionary<>
。