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

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

相关推荐
阿巴~阿巴~1 小时前
深入解析C++ STL链表(List)模拟实现
开发语言·c++·链表·stl·list
一枚小小程序员哈5 小时前
基于微信小程序的家教服务平台的设计与实现/基于asp.net/c#的家教服务平台/基于asp.net/c#的家教管理系统
后端·c#·asp.net
Eternity_GQM7 小时前
【Word VBA Zotero 引用宏错误分析与改正指南】【解决[21–23]参考文献格式插入超链接问题】
开发语言·c#·word
cimeo11 小时前
【C 学习】06-算法&程序设计举例
c#
百锦再12 小时前
.NET 的 WebApi 项目必要可配置项都有哪些?
java·开发语言·c#·.net·core·net
WYH2871 天前
C#控制台输入(Read()、ReadKey()和ReadLine())
开发语言·c#
hqwest1 天前
C#WPF实战出真汁06--【系统设置】--餐桌类型设置
c#·.net·wpf·布局·分页·命令·viewmodel
做一位快乐的码农1 天前
基于.net、C#、asp.net、vs的保护大自然网站的设计与实现
c#·asp.net·.net
DavieLau1 天前
C#项目WCF接口暴露调用及SOAP接口请求测试(Python版)
xml·服务器·开发语言·python·c#
张人玉1 天前
C#Encoding
开发语言·c#