.NET源码中的SortedDictionary<TKey, TValue>和SortedList<TKey, TValue>
2014-07-01 11:05
483 查看
SortedDictionary<TKey, TValue>和SortedList<TKey, TValue>的功能相同,都用来存储按Key排序的键值对,且无重复。
而内部实现的差异却很大,SortedDictionary<TKey, TValue>的内部实现是红黑二叉搜索树,而SortedList<TKey, TValue>的内部是两个数组,分别存储Key和Value序列。
这就决定了:
SortedList<TKey, TValue>的内存占用的少,因为树上还要存储左右树和红标识。
但是插入的删除的话数组要比树慢。树是O(log2N),数组是O(N)。
而插入已排序的数据的话,数组要快。
SortedList<TKey, TValue>的内部数据结构定义如下:
可以看到两个数组用来存储keys和values。而数组的最大长度是2GB.
而SortedDictionary<TKey, TValue>的内部数据结构定义如下:
内部其实是一个TreeSet的键值对泛型,而TreeSet则是继承于SortedSet红黑树。
其中的KeyValuePair<TKey, TValue>的定义如下:
然后对SortedDictionary<TKey, TValue>的增删改查就都是按照SortedSet<T>红黑树的操作了。
而SortedList<TKey, TValue>的增,查,删的实现分别如下:
增:先二分查找到要插入的位置,
然后插入:插入的时候要将目标位置之后的所有数据都向后移。。
删:先通过Key的找到要删除的位置索引
找到索引的过程是这样的:还是二分查找。
而根据索引删除的过程如下:把索引之后所有数据前移,然后把最后一个位置赋值为default<T>。
直接根据数组索引Key来get和set Value的实现如下:
以上。
而内部实现的差异却很大,SortedDictionary<TKey, TValue>的内部实现是红黑二叉搜索树,而SortedList<TKey, TValue>的内部是两个数组,分别存储Key和Value序列。
这就决定了:
SortedList<TKey, TValue>的内存占用的少,因为树上还要存储左右树和红标识。
但是插入的删除的话数组要比树慢。树是O(log2N),数组是O(N)。
而插入已排序的数据的话,数组要快。
SortedList<TKey, TValue>的内部数据结构定义如下:
可以看到两个数组用来存储keys和values。而数组的最大长度是2GB.
public class SortedList<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable { private static TKey[] emptyKeys = new TKey[0]; private static TValue[] emptyValues = new TValue[0]; private TKey[] keys; private TValue[] values; private int _size; private int version; private IComparer<TKey> comparer; private SortedList<TKey, TValue>.KeyList keyList; private SortedList<TKey, TValue>.ValueList valueList; [NonSerialized] private object _syncRoot; private const int _defaultCapacity = 4; private const int MaxArrayLength = 2146435071;
而SortedDictionary<TKey, TValue>的内部数据结构定义如下:
内部其实是一个TreeSet的键值对泛型,而TreeSet则是继承于SortedSet红黑树。
public class SortedDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable { [NonSerialized] private SortedDictionary<TKey, TValue>.KeyCollection keys; [NonSerialized] private SortedDictionary<TKey, TValue>.ValueCollection values; private TreeSet<KeyValuePair<TKey, TValue>> _set;
其中的KeyValuePair<TKey, TValue>的定义如下:
public struct KeyValuePair<TKey, TValue> { private TKey key; private TValue value;
然后对SortedDictionary<TKey, TValue>的增删改查就都是按照SortedSet<T>红黑树的操作了。
而SortedList<TKey, TValue>的增,查,删的实现分别如下:
增:先二分查找到要插入的位置,
public void Add(TKey key, TValue value) { if ((object) key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); int num = Array.BinarySearch<TKey>(this.keys, 0, this._size, key, this.comparer); if (num >= 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate); this.Insert(~num, key, value); }
然后插入:插入的时候要将目标位置之后的所有数据都向后移。。
private void Insert(int index, TKey key, TValue value) { if (this._size == this.keys.Length) this.EnsureCapacity(this._size + 1); if (index < this._size) { Array.Copy((Array) this.keys, index, (Array) this.keys, index + 1, this._size - index); Array.Copy((Array) this.values, index, (Array) this.values, index + 1, this._size - index); } this.keys[index] = key; this.values[index] = value; ++this._size; ++this.version; }
删:先通过Key的找到要删除的位置索引
public bool Remove(TKey key) { int index = this.IndexOfKey(key); if (index >= 0) this.RemoveAt(index); return index >= 0; }
找到索引的过程是这样的:还是二分查找。
public int IndexOfKey(TKey key) { if ((object) key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); int num = Array.BinarySearch<TKey>(this.keys, 0, this._size, key, this.comparer); if (num < 0) return -1; else return num; }
而根据索引删除的过程如下:把索引之后所有数据前移,然后把最后一个位置赋值为default<T>。
public void RemoveAt(int index) { if (index < 0 || index >= this._size) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); --this._size; if (index < this._size) { Array.Copy((Array) this.keys, index + 1, (Array) this.keys, index, this._size - index); Array.Copy((Array) this.values, index + 1, (Array) this.values, index, this._size - index); } this.keys[this._size] = default (TKey); this.values[this._size] = default (TValue); ++this.version; }
直接根据数组索引Key来get和set Value的实现如下:
public TValue this[TKey key] { get { int index = this.IndexOfKey(key); if (index >= 0) return this.values[index]; ThrowHelper.ThrowKeyNotFoundException(); return default (TValue); } set { if ((object) key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); int index = Array.BinarySearch<TKey>(this.keys, 0, this._size, key, this.comparer); if (index >= 0) { this.values[index] = value; ++this.version; } else this.Insert(~index, key, value); } }
以上。
相关文章推荐
- [C#]泛型与非泛型集合类的区别及使用例程,包括ArrayList,Hashtable,List<T>,Dictionary<Tkey,Tvalue>,SortedList<Tkey,Tvalue>,
- Dictionary<TKey, TValue> 的foreach便利方法
- .Net集合类的研究-有序集合(二)-SortedDictionary<TKey,TValue>
- C# Dictionary的用法 KeyValuePair<TKey, TValue> 结构
- .net学习笔记----有序集合SortedList、SortedList<TKey,TValue>、SortedDictionary<TKey,TValue>
- .net集合类的研究-哈希表(一)--Hashtable,Dictionary<TKey,TValue>
- Dictionary<TKey, TValue>.ContainsKey 方法 不区分大小写
- Dictionary、List<KeyValuePair<i>>的组合使用
- .net集合类的研究-哈希表(一)--Hashtable,Dictionary<TKey,TValue>
- c# 扩展方法奇思妙用基础:Dictionary<TKey, TValue> 扩展
- .Net集合类的研究-有序集合(一)-SortedList、SortedList<TKey,TValue>
- C# SortedDictionary<TKey,TValue>排序 用法 Sort()用法
- .net源码分析 - ConcurrentDictionary<TKey, TValue>
- .net源码分析 - ConcurrentDictionary<TKey, TValue>
- 【Android数据传递】Intent传递List和Object和List<Object>(附源码)
- .Net:再现List<T>:相关方法使用
- ArrayList、List<T>、HashSet<T>、LinkedList<T>各自优点和缺点,Dictionary<K,V>的内部存储数据方式有什么特殊的?
- 将正则表达式处理的内容转换到Dictionary<key, value>中
- .Net集合类的研究-有序集合(二)-SortedDictionary<TKey,TValue>
- 遍历List<T>包含字典Dictionary和其他字段dataGridView绑定数据