在 C# 开发中,Dictionary<TKey, TValue>
(简称 Dictionary)是一种非常常用且高效的数据结构。它也可以帮助我们快速访问、管理大量的键值对。在本文中,我们将结合示例详细介绍 Dictionary 的使用场景、常用操作以及最佳实践,帮助你更好地理解 C# 字典在实际业务中的运用。
Dictionary<TKey, TValue>
是 C# 基础类库中提供的泛型集合类型,用于存储键值对(Key-Value pair)。
快速查找
Dictionary 使用哈希表(Hash Table)实现,能提供平均 O(1) 的查找速度,也就是说,随着元素数量的增多,其访问效率依然较为稳定和高效。
无序集合
Dictionary 中元素存储顺序并不一定与插入顺序一致,无法按照加入的顺序来遍历获取,需要注意这一点。
泛型支持
Dictionary<TKey, TValue>
支持指定键和值的数据类型,能更好地利用类型安全。
应用场景广
以下为 Dictionary 中常见的方法和属性:
Add(TKey key, TValue value)
添加新的键值对。若键已存在,会抛出异常。
Remove(TKey key)
根据键删除对应的键值对。
ContainsKey(TKey key)
判断字典中是否包含指定键。
ContainsValue(TValue value)
判断字典中是否包含指定值。
TryGetValue(TKey key, out TValue value)
尝试获取与指定键关联的值,避免在键不存在时发生异常。
this[TKey key](索引器)
获取或设置与指定键相关联的值。但若键不存在,直接访问会抛出异常,因此推荐配合 TryGetValue()
使用。
C#using System;
using System.Collections.Generic;
namespace AppDictionary
{
internal class Program
{
static void Main(string[] args)
{
// 1. 创建一个 Dictionary,键为 string,值为 int
Dictionary<string, int> ages = new Dictionary<string, int>();
// 2. 使用 Add 方法添加键值对
ages.Add("Alice", 30);
ages.Add("Bob", 25);
// 3. 通过索引器方式添加或修改数据
ages["Charlie"] = 28;
// 4. 遍历字典中的所有键值对
foreach (KeyValuePair<string, int> kvp in ages)
{
Console.WriteLine($"Name: {kvp.Key}, Age: {kvp.Value}");
}
// 5. 检查字典中是否包含某个键
if (ages.ContainsKey("Alice"))
{
Console.WriteLine("找到 Alice,Age = " + ages["Alice"]);
}
// 6. 使用 TryGetValue 方法安全地获取值
if (ages.TryGetValue("Bob", out int bobAge))
{
Console.WriteLine("找到 Bob,Age = " + bobAge);
}
// 7. 使用 Remove 方法移除键值对
ages.Remove("Charlie");
// 移除后再次检查
if (!ages.ContainsKey("Charlie"))
{
Console.WriteLine("Charlie 已从字典中移除");
}
}
}
}
在 C# 中,结合 LINQ(Language Integrated Query)可以更灵活地对 Dictionary 进行查询和操作。下面示例展示了如何在字典里使用 LINQ 筛选出符合条件的项目,并倒序排列它们的值。
C#using System;
using System.Collections.Generic;
using System.Linq;
namespace AppDictionary
{
internal class Program
{
static void Main(string[] args)
{
// Dictionary 初始化
Dictionary<string, int> scores = new Dictionary<string, int>()
{
{"Alice", 95},
{"Bob", 80},
{"Charlie", 85},
{"David", 90}
};
// 查找分数大于 85 的学生,并按照分数倒序
var highScores = scores.Where(kvp => kvp.Value > 85)
.OrderByDescending(kvp => kvp.Value);
Console.WriteLine("High Scores:");
foreach (var score in highScores)
{
Console.WriteLine($"{score.Key}: {score.Value}");
}
// 转换为新的映射关系:成绩转化为 A、B、C
Dictionary<string, string> gradeMap =
scores.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value >= 90 ? "A" : kvp.Value >= 80 ? "B" : "C"
);
Console.WriteLine("Grade Map:");
foreach (var item in gradeMap)
{
Console.WriteLine($"{item.Key}: {item.Value}");
}
}
}
}
在实际开发中,配合 LINQ 能够大幅度提高数据处理的可读性和开发效率,无论是进行过滤、排序还是进行数据转换都非常方便。
Dictionary 非常适合做数据统计的场景,例如:统计文本中每个单词出现的次数。
C#using System;
using System.Collections.Generic;
namespace AppDictionary
{
internal class Program
{
static void Main(string[] args)
{
string text = "the quick brown fox jumps over the lazy dog";
Dictionary<string, int> wordCount = new Dictionary<string, int>();
// 分割文本并统计每个单词出现的次数
foreach (string word in text.Split(' '))
{
if (wordCount.ContainsKey(word))
{
wordCount[word]++;
}
else
{
wordCount[word] = 1;
}
}
// 输出统计结果
foreach (var item in wordCount)
{
Console.WriteLine($"单词 '{item.Key}' 出现了 {item.Value} 次");
}
}
}
}
在一些场景下,为了防止重复计算,可以使用 Dictionary 作为简单的缓存容器。下面演示用 GetOrAdd
方法完成缓存逻辑的思路:
C#using System;
using System.Collections.Generic;
namespace AppDictionary
{
internal class Program
{
static void Main(string[] args)
{
var cache = new SimpleCache<string, int>();
// 第一次访问时,值不存在,需要调用工厂方法计算
int value = cache.GetOrAdd("key1", k => 100);
Console.WriteLine(value);
// 第二次访问同一个键,直接从缓存返回,无需重新计算
int sameValue = cache.GetOrAdd("key1", k => 200);
Console.WriteLine(sameValue);
}
}
public class SimpleCache<TKey, TValue>
{
private Dictionary<TKey, TValue> _cache = new Dictionary<TKey, TValue>();
public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
{
if (!_cache.TryGetValue(key, out TValue value))
{
value = valueFactory(key);
_cache[key] = value;
}
return value;
}
public void Remove(TKey key)
{
_cache.Remove(key);
}
}
}
上例展示了通过 TryGetValue
来检查缓存中是否已存在对应 Key 的值,如果不存在则使用 委托 去生成并存储,再返回给调用方。
使用 TryGetValue
代替索引器
尽量使用 TryGetValue(key, out value)
来获取值,避免出现 KeyNotFoundException
异常。
考虑并发安全
在多线程环境下使用 Dictionary
时,请考虑线程安全问题。可以使用 lock
机制或使用线程安全版本的 ConcurrentDictionary<TKey, TValue>
。
及时释放或移除无用数据
Dictionary 无法自动清理,若要防止内存浪费,应及时调用 Remove
或重新初始化字典。
合理设置容量
如果已经知道字典大致存储多少条(如数百万级),可以在初始化时为 Dictionary 提供容量参数,减少后续扩容带来的性能开销。
应用在高频检索场景
例如:
注意内存占用
对于超大规模数据(如上百万级别),需要权衡内存开销与检索效率之间的平衡,合理使用数据结构及数据库或其它缓存。
在 C# 开发中,Dictionary<TKey, TValue>
提供了快速查找、灵活存储和高效管理的特性,是构建许多功能性模块(如缓存系统、统计表、设置管理等)的核心工具。
通过本文你可以了解到:
无论是在处理少量数据还是大量数据时,只要场景需要快速查找或键值映射,Dictionary
都能有效提升程序的可维护性和性能。结合本文提供的诸多示例,你可以在实际项目中更加得心应手地使用 C# 的字典结构来解决问题。祝你编程愉快!
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!