You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中Foreach循环内查询大列表过慢,寻求性能优化方法

优化C#中跨列表匹配的性能问题

你的核心问题在于每次循环都对20万条数据的anotherList执行线性查找(Any方法会遍历整个列表直到找到匹配项),时间复杂度为O(M*N)(M是第一个列表的元素数,N是20万),随着数据量增大,性能会急剧下降。

优化方案:用哈希集合预处理匹配键

将anotherList中的匹配条件(id+line)转换成哈希集合,把每次O(N)的线性查找变成O(1)的哈希查找,总时间复杂度降至O(M+N),大幅提升性能。

具体实现(使用ValueTuple作为键)

ValueTuple默认支持值类型和字符串的相等判断与哈希计算,无需额外实现方法:

// 预处理:将anotherList的(id, line)存入HashSet
var existingIdLinePairs = new HashSet<(int Id, string Line)>(
    anotherList.Select(item => (item.id, item.line))
);

// 遍历原列表时直接用哈希集合判断
foreach (var dto in List)
{
    if (existingIdLinePairs.Contains((dto.id, dto.line)))
        continue;
    
    // 你的其他业务逻辑
}

自定义类型作为键的情况(如果需要)

若id或line是自定义类型,需实现IEquatable<T>并重写哈希与相等方法,确保HashSet能正确判断:

public class IdLinePair : IEquatable<IdLinePair>
{
    public int Id { get; set; }
    public string Line { get; set; }

    public bool Equals(IdLinePair other)
    {
        if (other == null) return false;
        return Id == other.Id && string.Equals(Line, other.Line, StringComparison.Ordinal);
    }

    public override bool Equals(object obj) => Equals(obj as IdLinePair);

    public override int GetHashCode()
    {
        unchecked
        {
            // 组合哈希值,减少碰撞概率
            return (Id.GetHashCode() * 397) ^ (Line?.GetHashCode() ?? 0);
        }
    }
}

// 预处理
var existingPairs = new HashSet<IdLinePair>(
    anotherList.Select(item => new IdLinePair { Id = item.id, Line = item.line })
);

// 循环判断
foreach (var dto in List)
{
    if (existingPairs.Contains(new IdLinePair { Id = dto.id, Line = dto.line }))
        continue;
    
    // 其他逻辑
}

补充说明

  • 预处理只需要执行一次,不要放在循环内部,否则会抵消性能收益
  • 字符串比较建议指定StringComparison(比如Ordinal),避免默认的文化敏感比较带来的额外开销
  • 如果anotherList是频繁更新的集合,需要权衡预处理的开销;但如果是只读或少更新的集合,这种优化效果最明显

内容的提问来源于stack exchange,提问作者Diego Lins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 18:32:19