【实战】提升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
  • 如果是多字段组合查询,构建复合索引。
  • 如果数据较多且一次性查询,考虑使用排序加二分查找。
  • 对于性能要求极高的场景,可以结合缓存或并行查询优化。

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

相关推荐
XiaoZhenHua9813 小时前
C#工业机器视觉Recipe配方系统设计:多型号、多相机、多工位参数如何统一管理
c#·软件架构·机器视觉·工业自动化·工业软件·recipe
蓝速科技14 小时前
企业展厅数字人导览效果提升与选型实战指南丨蓝速科技
大数据·运维·数据库·人工智能·科技·microsoft
fujisheng66114 小时前
FUI 导航实践:拆开 Layer、History、Coverage 与 Cache 的组合语义
c#·unity3d
淡海水16 小时前
10-05-高级-模式匹配-CSharp如何改变与数据结构的交互方式
数据结构·算法·c#·模式匹配
XiaoZhenHua9817 小时前
C# WinForms + 西门子S7 + SQLite + EPPlus生产数据采集系统架构设计
系统架构·sqlite·c#
Lost of 程序猿18 小时前
船岸数据同步链路实战:SendFlag、单调版本号与断网三天后的续传
后端·c#·asp.net
AI推荐率1 天前
想让AI在选购问题中推荐品牌,应该找什么类型的服务商?
大数据·人工智能·microsoft
cjp5601 天前
012.UG二次开发,UG管道服务器与WPF管道通讯,传输JSON数据
c#
jiushidt2 天前
ArcGIS Pro Add‑in 打包流程详解
arcgis·c#·.net·arcgispro
呆呆在发呆.2 天前
Agnet狼人杀
人工智能·python·microsoft