【实战】提升List性能方法有几何

在内存中的 List<T> 上使用 LINQ 查询时,加索引并不像数据库那样有内置支持,但可以通过以下方式提高查询性能:


1. 手动构建索引

可以手动构建一个字典 (Dictionary<TKey, TValue>),将需要查询的字段作为键,值为对应的数据。查询时直接利用字典的 O(1) 查找性能。

示例代码:
csharp 复制代码
// 假设有一个类
public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}

// 构建索引
var employees = new List<Employee>
{
    new Employee { Id = 1, Name = "Alice" },
    new Employee { Id = 2, Name = "Bob" },
    new Employee { Id = 3, Name = "Charlie" }
};

// 创建索引
var employeeIndex = employees.ToDictionary(e => e.Id, e => e);

// 查询时使用索引
int searchId = 2;
if (employeeIndex.TryGetValue(searchId, out var employee))
{
    Console.WriteLine($"Found: {employee.Name}");
}
else
{
    Console.WriteLine("Not Found");
}

2. 预先分组以提高查询性能

对于需要多次按某个字段查询的场景,可以使用 Lookup<TKey, TElement> 预分组数据。Lookup 类似于 Dictionary,但支持一个键对应多个值。

示例代码:
csharp 复制代码
// 构建分组索引
var employeeLookup = employees.ToLookup(e => e.Name);

// 按 Name 查询
string searchName = "Alice";
foreach (var emp in employeeLookup[searchName])
{
    Console.WriteLine($"Found: {emp.Name} with Id: {emp.Id}");
}

3. 自定义数据结构

如果查询条件多样化,可以构建多字段索引,类似于复合索引。

示例代码:
csharp 复制代码
// 复合索引
var compositeIndex = employees.ToDictionary(e => (e.Id, e.Name), e => e);

// 查询
var key = (Id: 1, Name: "Alice");
if (compositeIndex.TryGetValue(key, out var result))
{
    Console.WriteLine($"Found: {result.Name}");
}

4. 排序后使用二分查找

如果 List<T> 是按查询字段排序的,可以使用 BinarySearch 来快速查找。

示例代码:
csharp 复制代码
// 排序列表
employees = employees.OrderBy(e => e.Id).ToList();

// 二分查找
int searchId = 2;
var found = employees.BinarySearch(
    new Employee { Id = searchId },
    Comparer<Employee>.Create((x, y) => x.Id.CompareTo(y.Id))
);

if (found >= 0)
{
    Console.WriteLine($"Found: {employees[found].Name}");
}
else
{
    Console.WriteLine("Not Found");
}

5. 使用缓存优化查询

如果查询是频繁且集中在某些字段上,可以构建一个缓存层,例如使用 MemoryCache

示例代码:
csharp 复制代码
using System.Runtime.Caching;

// 创建缓存
var cache = MemoryCache.Default;
string cacheKey = "EmployeeById";
cache[cacheKey] = employeeIndex; // 使用之前构建的字典

// 查询缓存
if (cache.Contains(cacheKey))
{
    var cachedIndex = (Dictionary<int, Employee>)cache[cacheKey];
    if (cachedIndex.TryGetValue(2, out var cachedEmployee))
    {
        Console.WriteLine($"From Cache: {cachedEmployee.Name}");
    }
}

6. 结合并行查询

对于大规模数据,可以结合并行 LINQ (PLINQ) 提高查询速度。

示例代码:
csharp 复制代码
// 使用 PLINQ
var result = employees.AsParallel()
    .Where(e => e.Name.StartsWith("A"))
    .ToList();

foreach (var emp in result)
{
    Console.WriteLine($"Found: {emp.Name}");
}

总结

加索引的方法需要根据具体场景选择:

  • 如果查询频繁,使用 DictionaryLookup
  • 如果是多字段组合查询,构建复合索引。
  • 如果数据较多且一次性查询,考虑使用排序加二分查找。
  • 对于性能要求极高的场景,可以结合缓存或并行查询优化。

根据你的需求,可以选用其中一个或多个组合方式。

相关推荐
暖馒7 小时前
Modbus应用层协议的深度剖析
网络·网络协议·c#·wpf·智能硬件
刘欣的博客11 小时前
C# CS架构程序发版升级的走数据库方案
c#·单文件升级自己的方式
Yorlen_Zhang12 小时前
Python Tkinter Text 控件完全指南:从基础编辑器到富文本应用
开发语言·python·c#
不绝19112 小时前
C#进阶:预处理指令/反射,Gettype,Typeof/关键类
开发语言·c#
大鹏说大话12 小时前
告别 MSBuild 脚本混乱:用 C# 和 Nuke 构建清晰、可维护的现代化构建系统
开发语言·c#
czhc114007566314 小时前
通信 28
c#
bugcome_com17 小时前
C# 程序结构详解:从 Hello World 开始
c#
唐梓航-求职中18 小时前
编程-技术-算法-leetcode-288. 单词的唯一缩写
算法·leetcode·c#
千逐6819 小时前
多物理场耦合气象可视化引擎:基于 Flutter for OpenHarmony 的实时风-湿-压交互流体系统
flutter·microsoft·交互
吹牛不交税20 小时前
安装Framework4.0时提示:Microsoft .NET Framework 4 已是此操作系统的一部分。不需要安装 .NET Framework
microsoft·.net