ConcurrentDictionary.对于基于int数组(Key字段)的筛选,速度非常慢



我有以下

  var links = new ConcurrentDictionary<int, Link>();

它填充了大约20k条记录,我有另一个字符串数组(List),我使用以下方法将其转换为int数组。

var intPossible = NonExistingListingIDs.Select(int.Parse); //this is very fast but need to be done

这是相当快的。但我想创建一个新的列表,或者只筛选出与ConcurrentDictionary的Key元素匹配的intPossible数组中实际存在的"链接"。

我使用了where子句,但实际过滤需要大约50秒,这对我想做的事情来说非常慢

var filtered = links.Where(x => intPossible.Any(y => y == x.Key)).ToList();

我知道intersect很快,但我有一个int数组,而intersect不能针对ConcurrentDictionary 使用它

我如何过滤链接,使其更快一点,而不是50秒。

您需要用更快速的东西来替换O(n)内部查找,比如为查找提供O(1)复杂性的哈希集。

所以

var intPossible = new HashSet<int>(NonExistingListingIDs.Select(int.Parse));

var filtered = links.Where(x => intPossible.Contains(x.Key)).ToList();

这将避免对links中的每个项目迭代大部分intPossible

或者,林克是你的朋友:

var intPossible = NonExistingListingIDs.Select(int.Parse);
var filtered =
  links.Join(intPossible, link => link.Key, intP => intP, (link, intP) => link);

Join的实现与我上面所做的基本相同。

另一种方法是枚举列表并使用字典的索引器。。。可能会干净一点。。。

var intPossible = NonExistingListingIDs.Select(int.Parse);
var filtered = from id in intPossible
               where links.ContainsKey(id)
               select links[id];

你可能也想在里面放一个.ToList()。。。

这实际上应该比@spender的解决方案稍微快一点,因为.Join必须创建一个新的HashTable,而此方法使用ConcurrentDictionary中的HashTable。

最新更新