我需要维护一个唯一键控的数据库对象的缓存(按整数)。查询提供了IEnumerable<MyEntity>
(MyEntity
使用int
主键)的实例和结果,我想尽快初始化Dictionary<int, MyEntity>
的实例,因为这个查询可以返回几十万行。
从Dictionary<int, MyEntity>
初始化IEnumerable<MyEntity>
实例的最佳效果是什么?
简而言之,我想知道是否有更高效的方法:
IEnumerable<MyEntity> entities = DoSomeQuery();
var cache = new Dictionary<int, MyEntity>();
foreach (var entity in entities)
cache.Add(entity.Id, entity);
//or...
cache = entities.ToDictionary(e => e.Id);
当然,该查询具有最大的潜在性能影响,但重要的是,无论我在哪个用例中,我都要花几毫秒。
修改:
值得注意的是,.ToDictionary<TKey, TElement>
literally runs a foreach loop就像第一个例子一样,所以人们可以假设,如果不是稍微差一点,那将是完全相同的。也许这就是我的答案。
答案 0 :(得分:5)
你的速度和你一样快。
如果您可以快速确定要添加的元素数量,那么将其作为容量传递给Dictionary
构造函数将通过阻止内部调整大小操作(.NET Core版本的ToDictionary()
这样做,其他版本没有。)
如果按键相对紧密,那么您可以从调整到范围而不是计数中受益。例如。如果您有Id
{5, 6, 7, 9, 10, 11}
,那么将大小设置为7(如果缺少8
那时您将拥有的值的数量)而不是6是有益的。(实际上,它在这里没有任何区别,因为效果只会在比这更大的集合中起作用)。但是效果相当小,所以如果你要浪费大量的内存就不值得做(例如,它绝对不值得将{8, 307}
存储在一个300容量的字典中!这种好处来自增加频率在内部大小(因此内部散列减少)小于完成全部添加时的内容时,key将被散列到不会与其他元素冲突的内容。
如果它们紧密包装但您无法预测尺寸,那么将它们按顺序存储是有好处的,因为随着内部存储的增长,通常会出现字典希望存储某些内容的情况。未使用的简化哈希码。虽然好处将小于内存中排序的成本(并且无论如何都需要明确地或在OrderBy
操作中找到元素的数量),所以只有获得这种排序的方法才有用为你做得便宜。 (例如,某些web服务要求给出某些类别的排序标准,因此您也可以将id作为标准。大多数情况下这不适用。)
这些点,特别是最后两点,虽然是微小的效果,但可能不会增加任何可衡量的效果。即使第一个小于获得计数的成本,如果它还没有在具有便宜的Count
或Length
操作的来源中。
foreach
本身也许可以通过替换索引(适用时)来改进,但有时也会更糟。它也往往在一些具体类型的源上做得更好(即foreach
T[]
foreach
List<T>
foreach
IEnumerable<T>
void readData()
{
int **arr,m;
scanf("%d",&m);
arr = (int **)malloc(sizeof(int)*m);
for(int i=0;i<m;i++)
{
arr[i] = (int *)malloc(sizeof(int) * 2);
}
for(int i=0;i<m;i++)
{
printf("..%d ..\n",i); // if m = 20 then running only 12 times
scanf("%d %d",&arr[i][0],&arr[i][1]);
}
}
int main()
{
readData();
}
{{1}} {{1}} )但这意味着在层之间公开实现细节并且很少值得,特别是因为许多集合类型没有任何好处。