我发现 SortedList<TKey, TValue>
、SortedDictionary<TKey, TValue>
和 Dictionary<TKey, TValue>
实现了相同的接口。
- 什么时候我们应该选择使用
SortedList
和SortedDictionary
而不是Dictionary
? - 在应用程序方面,
SortedList
和SortedDictionary
有什么区别?
我发现 SortedList<TKey, TValue>
、SortedDictionary<TKey, TValue>
和 Dictionary<TKey, TValue>
实现了相同的接口。
SortedList
和 SortedDictionary
而不是 Dictionary
?SortedList
和 SortedDictionary
有什么区别?当迭代其中任意一个时,元素将被排序。但Dictionary<T,V>
不会。
MSDN解释了SortedList<T,V>
和SortedDictionary<T,V>
的区别:
SortedDictionary(TKey, TValue)
是一个带有O(log n)检索的二叉搜索树,这里的n是字典中元素的数量。在这方面,它类似于SortedList(TKey, TValue)
泛型类。两个类拥有相似的对象模型,并且都具有O(log n)检索。两个类的区别在于内存使用和插入/删除速度:
SortedList(TKey, TValue)
使用比SortedDictionary(TKey, TValue)
更少的内存。
SortedDictionary(TKey, TValue)
对于未排序的数据具有更快的插入和删除操作:O(log n)而不是SortedList(TKey, TValue)
的O(n)。如果列表一次性从已排序的数据中填充,则
SortedList(TKey, TValue)
比SortedDictionary(TKey, TValue)
更快。
SortedList
中,您可以通过索引检索(与按键值检索相反),而在SortedDictionary
中则不行。 - Andrew Savinykh我想提及字典之间的区别。
上面的图片显示Dictionary<K,V>
在每种情况下都比Sorted
快或相等,但如果需要元素的顺序,例如打印它们,就选择Sorted
。
为了总结性能测试 - SortedList vs. SortedDictionary vs. Dictionary vs. Hashtable的结果,不同场景下从最好到最差的结果如下:
内存使用:
SortedList<T,T>
Hashtable
SortedDictionary<T,T>
Dictionary<T,T>
插入:
Dictionary<T,T>
Hashtable
SortedDictionary<T,T>
SortedList<T,T>
搜索操作:
Hashtable
Dictionary<T,T>
SortedList<T,T>
SortedDictionary<T,T>
foreach循环操作
SortedList<T,T>
Dictionary<T,T>
Hashtable
SortedDictionary<T,T>
sorted
的含义:当你使用 For Each MyItem in Collection
而不是按照你最初 .Add
添加这些项的顺序进行处理时,一个经过 sorted
的 Collection
将根据 Key
值上的标准(由 IComparer
定义)对它们进行排序。例如,如果你的 Keys 是字符串,则默认情况下,你的 Collection 将按照你的 Keys 的字母顺序进行处理,但你始终可以定义自定义排序规则。 - AmaSystem.Collections.Generic
命名空间中的所有类型。
字典可能是最常用的关联式容器类。字典是最快的关联查找/插入/删除类,因为它在内部使用哈希表。由于键是哈希的,所以键类型应正确实现GetHashCode()和Equals()或者在构造时提供外部IEqualityComparer给字典。字典中项的插入/删除/查找时间是分摊常数时间 - O(1) - 这意味着无论字典有多大,查找某个东西所需的时间都保持相对恒定。这对高速查找非常理想。唯一的缺点是,由于使用哈希表,字典是无序的,因此无法轻松按顺序遍历字典中的项。
SortedDictionary在用法上与Dictionary类似,但实现方式非常不同。 SortedDictionary在内部使用二叉树来按键维护项目的顺序。由于排序的结果,用于键的类型必须正确实现IComparable以便正确排序键。排序字典为了能够按键维护集合的顺序,牺牲了一点查找时间,因此排序字典中的插入/删除/查找时间是对数级别 - O(log n)。通常情况下,使用对数时间,你可以将集合的大小翻倍,并且只需要执行一个额外的比较即可找到该项。当您想要快速查找但又想按键维护集合顺序时,请使用SortedDictionary。
SortedList是通用容器中的另一种排序关联容器类。与SortedDictionary一样,SortedList使用一个键来对键值对进行排序。但与SortedDictionary不同的是,SortedList中的项目存储为已排序的项目数组。这意味着插入和删除是线性的-O(n)-因为删除或添加一个项目可能需要将所有项目向上或向下移动。然而,查找时间是O(log n),因为SortedList可以使用二进制搜索通过其键找到列表中的任何项。那么为什么要这样做呢?答案是如果您要预先加载SortedList,则插入会变慢,但由于数组索引比遵循对象链接更快,查找速度比SortedDictionary略快。再次强调,我建议在想要快速查找并希望按键维护集合顺序以及插入和删除较少的情况下使用此功能。
欢迎提供反馈,因为我肯定没有把所有东西都搞对。
n
。字典
内存
KeyArray(n) -> 非排序数组<指针>
ItemArray(n) -> 非排序数组<指针>
HashArray(n) -> 排序数组<哈希值>
添加
HashArray(n) = Key.GetHash
#O(1)KeyArray(n) = PointerToKey
#O(1)ItemArray(n) = PointerToItem
#O(1)删除
i = 0 to n
,找到 i
其中 HashArray(i) = Key.GetHash
# O(log n) (有序数组)HashArray(i)
# O(n) (有序数组)KeyArray(i)
# O(1)ItemArray(i)
# O(1)获取项
i = 0 to n
,找到 i
其中 HashArray(i) = Key.GetHash
# O(log n) (有序数组)ItemArray(i)
循环遍历
i = 0 to n
,返回 ItemArray(i)
SortedDictionary
内存
KeyArray(n) = 非排序指针数组
ItemArray(n) = 非排序指针数组
OrderArray(n) = 排序指针数组
添加
KeyArray(n) = PointerToKey
# O(1)ItemArray(n) = PointerToItem
# O(1)For i = 0 to n
,使用ICompare
查找i
,其中KeyArray(i-1) < Key < KeyArray(i)
# O(n)OrderArray(i) = n
# O(n)(排序数组)删除
For i = 0 to n
,查找i
,其中KeyArray(i).GetHash = Key.GetHash
# O(n)KeyArray(SortArray(i))
# O(n)ItemArray(SortArray(i))
# O(n)OrderArray(i)
# O(n)(排序数组)获取项目
For i = 0 to n
,查找i
,其中KeyArray(i).GetHash = Key.GetHash
# O(n)ItemArray(i)
循环遍历
For i = 0 to n
,返回ItemArray(OrderArray(i))
排序列表
内存
KeyArray(n) = 排序后的指针数组<pointer>
ItemArray(n) = 排序后的指针数组<pointer>
添加
对于 i = 0 到 n
,使用 ICompare
找到满足条件的 i
,其中 KeyArray(i-1) < Key < KeyArray(i)
# O(log n)KeyArray(i) = PointerToKey
# O(n)ItemArray(i) = PointerToItem
# O(n)删除
对于 i = 0 到 n
,找到满足条件的 i
,其中 KeyArray(i).GetHash = Key.GetHash
# O(log n)KeyArray(i)
# O(n)ItemArray(i)
# O(n)获取项目
对于 i = 0 到 n
,找到满足条件的 i
,其中 KeyArray(i).GetHash = Key.GetHash
# O(log n)ItemArray(i)
循环遍历
对于 i = 0 到 n
,返回 ItemArray(i)
当您在迭代集合时希望按键排序时,请使用SortedDictionary。如果您不需要数据排序,则更适合使用普通字典(Dictionary),它的性能更好。
SortedList和SortedDictionary基本上执行相同的操作,但是它们的实现方式不同,因此具有不同的优点和缺点,详见这里。
尝试为@Lev提出的每个案例分配一个性能分数,我使用了以下值:
结果如下(越高越好):
Dictionary: 12.0
SortedDictionary: 9.0
SortedList: 6.5
当然,每个使用案例都会更加重视某些操作。