Dictionary集合 #

一、Dictionary概述 #

Dictionary<K,V>是键值对集合,通过键快速查找值。

1.1 特点 #

  • 键唯一
  • 高效查找O(1)
  • 键值对存储
  • 实现IDictionary接口

1.2 创建Dictionary #

csharp
var dict1 = new Dictionary<string, int>();
var dict2 = new Dictionary<string, int>(100);
var dict3 = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92,
    ["王五"] = 78
};
var dict4 = new Dictionary<string, int>
{
    { "张三", 85 },
    { "李四", 92 }
};

二、添加元素 #

2.1 索引器添加 #

csharp
var scores = new Dictionary<string, int>();

scores["张三"] = 85;
scores["李四"] = 92;
scores["张三"] = 90;

2.2 Add方法 #

csharp
var scores = new Dictionary<string, int>();

scores.Add("张三", 85);
scores.Add("李四", 92);

try
{
    scores.Add("张三", 100);
}
catch (ArgumentException ex)
{
    Console.WriteLine($"键已存在:{ex.Message}");
}

2.3 TryAdd方法 #

csharp
var scores = new Dictionary<string, int>();

bool added1 = scores.TryAdd("张三", 85);
bool added2 = scores.TryAdd("张三", 100);

三、访问元素 #

3.1 索引器访问 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92
};

int score = scores["张三"];

try
{
    int notFound = scores["王五"];
}
catch (KeyNotFoundException ex)
{
    Console.WriteLine($"键不存在:{ex.Message}");
}

3.2 TryGetValue方法 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92
};

if (scores.TryGetValue("张三", out int score))
{
    Console.WriteLine($"张三的分数:{score}");
}

if (scores.TryGetValue("王五", out int notFound))
{
    Console.WriteLine($"王五的分数:{notFound}");
}
else
{
    Console.WriteLine("王五不存在");
}

3.3 GetValueOrDefault #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85
};

int score1 = scores.GetValueOrDefault("张三");
int score2 = scores.GetValueOrDefault("王五");
int score3 = scores.GetValueOrDefault("王五", 0);

四、删除元素 #

4.1 Remove方法 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92,
    ["王五"] = 78
};

bool removed1 = scores.Remove("张三");
bool removed2 = scores.Remove("不存在");

4.2 Remove方法(带值返回) #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85
};

if (scores.Remove("张三", out int removedScore))
{
    Console.WriteLine($"已删除:{removedScore}");
}

4.3 Clear方法 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92
};

scores.Clear();

五、查找与判断 #

5.1 ContainsKey方法 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92
};

bool hasZhangSan = scores.ContainsKey("张三");
bool hasWangWu = scores.ContainsKey("王五");

5.2 ContainsValue方法 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92
};

bool has85 = scores.ContainsValue(85);
bool has100 = scores.ContainsValue(100);

5.3 Count属性 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92
};

int count = scores.Count;
int countAbove80 = scores.Count(kvp => kvp.Value > 80);

六、遍历 #

6.1 遍历键值对 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92,
    ["王五"] = 78
};

foreach (var kvp in scores)
{
    Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}

6.2 遍历键 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92
};

foreach (var key in scores.Keys)
{
    Console.WriteLine(key);
}

6.3 遍历值 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92
};

foreach (var value in scores.Values)
{
    Console.WriteLine(value);
}

七、更新元素 #

7.1 索引器更新 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85
};

scores["张三"] = 90;

7.2 批量更新 #

csharp
var scores = new Dictionary<string, int>
{
    ["张三"] = 85,
    ["李四"] = 92
};

var newScores = new Dictionary<string, int>
{
    ["张三"] = 90,
    ["王五"] = 78
};

foreach (var kvp in newScores)
{
    scores[kvp.Key] = kvp.Value;
}

八、实战示例 #

8.1 缓存实现 #

csharp
public class Cache<TKey, TValue>
{
    private readonly Dictionary<TKey, TValue> _cache = new();
    private readonly TimeSpan _expiration;
    private readonly Dictionary<TKey, DateTime> _timestamps = new();
    
    public Cache(TimeSpan expiration)
    {
        _expiration = expiration;
    }
    
    public bool TryGet(TKey key, out TValue value)
    {
        if (_cache.TryGetValue(key, out value))
        {
            if (DateTime.Now - _timestamps[key] < _expiration)
            {
                return true;
            }
            Remove(key);
        }
        return false;
    }
    
    public void Set(TKey key, TValue value)
    {
        _cache[key] = value;
        _timestamps[key] = DateTime.Now;
    }
    
    public void Remove(TKey key)
    {
        _cache.Remove(key);
        _timestamps.Remove(key);
    }
    
    public void Clear()
    {
        _cache.Clear();
        _timestamps.Clear();
    }
}

8.2 分组统计 #

csharp
public static Dictionary<TKey, int> CountBy<TSource, TKey>(
    IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector)
{
    var result = new Dictionary<TKey, int>();
    
    foreach (var item in source)
    {
        var key = keySelector(item);
        if (!result.ContainsKey(key))
        {
            result[key] = 0;
        }
        result[key]++;
    }
    
    return result;
}

var words = new[] { "apple", "banana", "apple", "cherry", "banana", "apple" };
var counts = CountBy(words, w => w);

8.3 双向字典 #

csharp
public class BiDictionary<TKey, TValue>
{
    private readonly Dictionary<TKey, TValue> _forward = new();
    private readonly Dictionary<TValue, TKey> _reverse = new();
    
    public void Add(TKey key, TValue value)
    {
        if (_forward.ContainsKey(key) || _reverse.ContainsKey(value))
            throw new ArgumentException("键或值已存在");
        
        _forward[key] = value;
        _reverse[value] = key;
    }
    
    public bool TryGetByKey(TKey key, out TValue value)
        => _forward.TryGetValue(key, out value);
    
    public bool TryGetByValue(TValue value, out TKey key)
        => _reverse.TryGetValue(value, out key);
    
    public bool RemoveByKey(TKey key)
    {
        if (_forward.TryGetValue(key, out var value))
        {
            _forward.Remove(key);
            _reverse.Remove(value);
            return true;
        }
        return false;
    }
}

九、总结 #

Dictionary要点:

操作 方法
添加 Add, TryAdd, 索引器
访问 索引器, TryGetValue
删除 Remove, Clear
查找 ContainsKey, ContainsValue
遍历 Keys, Values, KeyValuePair

下一步,让我们学习队列与栈!

最后更新:2026-03-26