大列表比对赋值性能优化咨询及IEqualityComparer适用性疑问
优化列表比对赋值的高性能方案
首先得说,你原来的嵌套循环方案性能拉胯的核心原因是时间复杂度太高——双重foreach是O(n*m)的复杂度,5万条数据的话就是25亿次比较操作,30秒完全在意料之中。
最快的实现方案:用哈希字典做快速查找
解决这类问题的最优思路就是把其中一个列表转换成哈希字典,把查找操作从O(n)降到O(1),整体复杂度就变成了O(n+m),性能会有数量级的提升。
具体代码如下:
private void FindUPC(List<ResultItem> filteredProducts, List<zsp_select_UserItems_Result> items) { // 先把items列表转换成以ItemID为键的字典,这一步是O(m)时间 var itemLookup = items.ToDictionary(item => item.ItemID); // 遍历filteredProducts,通过字典快速匹配赋值,这一步是O(n)时间 foreach (var product in filteredProducts) { if (itemLookup.TryGetValue(product.ID, out var matchedItem)) { product.UPC = matchedItem.UPC; product.EAN = matchedItem.EAN; product.MPN = matchedItem.MPN; } } }
这个方案处理5万条数据的话,耗时应该会降到几十毫秒级别,完全解决你的性能问题。
关于IEqualityComparer的疑问
IEqualityComparer本身不能直接提升查找性能,但它可以帮你定义自定义的键相等规则。比如如果你的ItemID是字符串,需要忽略大小写比较,或者是自定义类型需要特殊的相等判断,就可以用它来扩展字典的查找逻辑:
// 示例:忽略字符串ItemID的大小写进行匹配 var itemLookup = items.ToDictionary(item => item.ItemID, StringComparer.OrdinalIgnoreCase);
如果你的ItemID是int、Guid这类默认相等逻辑就足够的值类型,那完全不需要额外的IEqualityComparer,默认的字典实现已经足够高效。
对你贴的修改代码的纠正
你贴的那个加了break的代码有逻辑错误:break放在了内层foreach的外面,这会导致内层循环只跑一次就退出,根本没机会找到匹配的项。正确的写法应该是找到匹配后立刻跳出内层循环:
private void FindUPC(List<ResultItem> filteredProducts, List<zsp_select_UserItems_Result> items) { foreach (var item in items) { foreach (var trItem in filteredProducts) { if (item.ItemID == trItem.ID) { trItem.UPC = item.UPC; trItem.EAN = item.EAN; trItem.MPN = item.MPN; break; // 找到匹配后立即停止内层循环 } } } }
不过就算修正了这个问题,这个方案的时间复杂度还是O(n*m),对于5万条数据来说依然很慢,还是推荐用字典的方案。
内容的提问来源于stack exchange,提问作者User987
相关产品推荐
相关产品推荐

