目录
TryGetValue(TKey key, out TValue value)
Remove(TKey key, out TValue value)
基本概念
Dictionary是一个泛型集合,它存储唯一键和值的集合,其中每个键都是唯一且与一个值关联的。Dictionary内部被视为是无序的,但Dictionary的查找时间复杂度是O(1),因此Dictionary通常用于存储不关心顺序、但需要频繁查找的数据。同时,Dictionary本身也是动态扩容的数据结构,因此不需要关心字典容量问题。
Dictionary与Hashtable:
事实上,无论是Dictionary还是Hashtable,其底层都是哈希表,但这并不意味着这两种数据结构是完全相同的:
性能消耗
从性能消耗上来讲,由于Dictionary是泛型的,因而使用字典时并不需要装箱、拆箱的操作,并且从Dictionary中取出数据进行操作时也不需要对数据进行类型判断,因而Dictionary效率更高。
Hashtable则不是泛型,其键和值都是object类型,因此使用Hashtable时免不了装箱、拆箱的操作,同时由于涉及拆箱,因此需要在拆箱前对数据进行类型判断,以防止错误的数据类型转换。
线程安全性
Dictionary并不是一个线程安全的数据结构,因此Dictionary更推荐在单线程的程序中使用;Hashtable是线程安全的因此在多线程程序中更推荐使用Hashtable
构造Dictionary
无参构造
这是Dictionary最基础的构造方式,但由于Dictionary本身带有自动扩容机制,而自动扩容机制会产生一定的性能消耗,因此更推荐构造时至少指定一个参考大小,以扩容次数,从而降低性能消耗。
Dictionary<int, int> _dict = new Dictionary<int, int>();
指定初始容量
这是常用的构造方式,如果能预估Dictionary存储键值对数量,则生成一个指定容量的Dictionary,这样可以减少自动扩容带来的性能消耗和空间浪费
Dictionary<int, int> _dict = new Dictionary<int, int>(10);
使用初始值
当已知字典要存储的键和值时,可以是用这种方式进行构造,这样可以生成后直接将键值对存进字典中
Dictionary<string, int> _dict = new Dictionary<string, int>()
{
["1+1"] = 3,
["2+2"] = 5,
["3+3"] = 7,
};
拷贝构造
当我们希望对Dictionary对象内的键值对进行增减,但又希望保留一份当前Dictionary数据时就会用到,拷贝构造可以从旧对象中生成新对象,两者数据相同但互不影响,但如果内部数据是引用类型,则需要注意,拷贝构造是浅拷贝,即如果存储的是引用类型,则拷贝的是对数据的引用而非引用的数据本身,例如:
class MyClass
{
public int data;
}
Dictionary<int, MyClass> _dictA = new Dictionary<int, MyClass>()
{
[0] = new MyClass(){ data = 10 }
};
Dictionary<int, MyClass> _dictB = new Dictionary<int, MyClass>(_dictA);
_dictB[0].data = 5;// 此时会发现_dictA[0].data也变成了5,因为拷贝构造执行的是浅拷贝
常用属性
Keys
Keys返回的是存储当前Dictionary中所有Key的一个集合,该集合通常用foreach进行遍历,也可以利用List的构造函数将其转变成一个List方便使用。
Dictionary<string, int> _dict = new Dictionary<string, int>()
{
["1+1"] = 3,
["2+2"] = 5,
["3+3"] = 7,
};
foreach (string _key in _dict.Keys)
{
Console.Write(_key);
}
List<string> _list_DictKeys = new List<string>(_dict.Keys);
Values
values返回的是当前Dictionary中所有value的一个集合,该集合通常用foreach进行遍历,也可以利用List的构造函数将其转变成一个List方便使用。
foreach (int _value in _dict.Values)
{
Console.Write(_value);
}
List<int> _list_DictValues = new List<int>(_dict.Values);
常用方法
Add(TKey key, TValue value)
这是最常用的像字典内添加键值对的方式,但值得注意的是,这一方法不会进行安全判定,即当字典中存在重复键时会导致报错
Dictionary<string, int> _dict = new Dictionary<string, int>();
_dict.Add("1+1", 2);
Dictionary[key] = value
Dictionary[key] = value也可以用于向字典内添加键值对,但是Dictionary[key] = value会进行安全判定,但是当字典中存在重复键时,会覆盖原数据
Dictionary<string, int> _dict = new Dictionary<string, int>();
_dict["1+1"] = 2;
_dict["1+1"] = 3;// 此时上一次添加的["1+1"] = 2被覆盖成了["1+1"] = 3
ContainsKey(TKey key)
用于查找字典当中是否包含某个Key,若包含则返回True,否则返回False
Dictionary<string, int> _dict = new Dictionary<string, int>();
_dict["1+1"] = 2;
bool _true = _dict.ContainsKey("1+1"); // True
bool _false = _dict.ContainsKey("2+2"); // False
ContainsValue(TValue value)
用于查找字典当中是否包含某个Value,若包含则返回True,否则返回False
Dictionary<string, int> _dict = new Dictionary<string, int>();
_dict["1+1"] = 2;
bool _true = _dict.ContainsValue(2); // True
bool _false = _dict.ContainsValue(999); // False
TryGetValue(TKey key, out TValue value)
尝试获取某个Key对应的Value,若包含则返回True,如果不包含查找的Key则返回false而非报错
Dictionary<string, int> _dict = new Dictionary<string, int>();
_dict["1+1"] = 2;
if (_dict.TryGetValue("1+1", out int value))// True
{
Console.Write(value); // 输出:2
}
Rmove(TKey)
用于移除某个键对应的键值对,如果输入的Key不存在,也不会抛出异常
Dictionary<string, int> _dict = new Dictionary<string, int>();
_dict["?"] = 2;
_dict.Remove("!");// 无事发生
_dict.Remove("?");// 移除["?"] = 2
Remove(TKey key, out TValue value)
用于移除某个键对应的键值对,同时可以获取这个键对应的值
Dictionary<string, int> _dict = new Dictionary<string, int>() { ["777"] = 777 };
_dict.Remove("777", out int value);
Console.Write(value);//输出: 777