The Anatomy Of Basic Data Structure, 基本数据结构解析
前言
这东西还是看STL最好,然而现在毕竟没有搞这方面的开发,于是就自己试下. 慢慢写着这个东西探索也有两个星期了,到这里也当一个结束好了,也许更应该是一个学习笔记这样的东西, 聊以自娱下, 善始不必善终,就当给搜索增加一条结果 哈哈.如果能给你带来帮助,当然是欣喜不过了 :)
本文逻辑
作者试图通过对SSCLI的探索,对于各种基本数据结构做一些比较与测试,试图找出各个数据结构之间的关系与最佳用法。 数据结构: Stack, Queue, ArrayList, List, SortedList, HashTable, Dictionary
如果您指向知道怎么用好,请跳到本文末尾查看 我眼中的最佳实践。 如果您对于数据结构的设计与原理感兴趣,不妨顺序读完。
认识他们
部分 | 链接 |
Stack & Queue |
基本数据结构解析之Stack & Queue |
ArrayList | 基本数据结构解析之ArrayList |
List<T> | 基本数据结构解析之List<T> |
HashTable & Dictionary | 数据结构 : Hash Table [I] 数据结构 : Hash Table [II] GetHashCode 是什么? |
SortedList | 插入排序 |
SortedDictionary | 红黑树 |
有些问题
- Stack, Queue 和 Stack<T>, Queue<T> 进行比较,那个快?
- Hashtable 和 Dictionary速度呢?
- SortedList 和 SortedDictionary 比较呢?
比较环境:
Visual Studio 2008 / Windows 2008 / .Net Framework 3.5 SP1
比较思路:
1. 进行插入,查找,删除操作速度比较
2. 设定Capacity
3. 插入行数 10000
4. 时间格式, Ticks(滴答数)
default |
Capacity |
|||||
Add |
Remove |
Contain |
Add |
Remove |
Contains |
|
Stack |
73824 |
4166 |
2036 |
135402 |
4025 |
2000 |
Stack<T> |
66375 |
7543 |
2973 |
64917 |
4354 |
2899 |
Queue |
68026 |
4900 |
2640 |
72499 |
4688 |
2532 |
Queue<T> |
108628 |
5098 |
3031 |
62562 |
4939 |
3694 |
ArrayList |
64808 |
1207944 |
1937 |
67122 |
1343826 |
1800 |
List<T> |
71740 |
1225703 |
3831 |
62169 |
1218216 |
2622 |
Hashtable |
198022 |
95981 |
112 |
356551 |
108 |
95993 |
Dictionary |
172952 |
98622 |
187 |
162696 |
111 |
87032 |
SortedList |
1006197 |
3032337 |
303 |
979317 |
252 |
3105849 |
SortedDictionary |
1189570 |
40215 |
247 |
1174315 |
229 |
926805 |
测试代码: 点击这里下载
再单独测试下Capcity + TrimExcess的性能
可以看到采用默认的方式最慢,最符合的Capacity最快,TrimExcess次之
原因是:
第一个需要频繁的扩容
第二个不需要
第三个则需要进行一次复制操作
可以参考开始时给出的链接 :)
我眼中的最佳实践
A. 使用泛型
使用泛型的建议是对于操作的方便性来说的,一点的性能损耗相比于编译器检查和可能带来的BUG而言算不上什么, 当然需要了解
- 对于值类型,泛型优于原始结构
- 对于引用类型,使用泛型第一次性能低于原始结构,但是差距很小.
- 对于Contains操作,泛型处于劣势
B. 设置默认的Capacity
如果您可以猜测出大概的Capacity, 不妨给他加上一些大小,如果您觉得过大,不妨加上一个Capacity. 对于小数据量而言,自己喜欢默认不带Capacity, 谁让他那么方便呢 :)
C. 在合适的场合用对应的数据结构
- 大容量数据存储需要快速读取值, 使用Hashtable / Dictionary
- 要对数据进行排序时使用对应的排序数据结构
D. 如果您不确定大小,使用HybridDictionary
他在默认16时会从ListDictionary扩容到Hashtable
E. 使用Array.BinarySearch() , Array.Sort()
使用一个已经被测试过无数次的排序方法和查找方法, 相信会更让您的程序更加健壮一些
F. 使用Array.ConvertAll, List<T>.ForEach() 等快速访问的方式
如果您还没有开始使用这些便捷的方式,现在开始吧.
G. 重写您自定义类型的GethashCode
也许,并不打算把他作为某个集合的索引,但是不能保证别人不用这个部分当索引 :(. 所以,当自定义类型的时候,重写GethashCode, 并明白GetHashCode的原理
H. 阅读System.Collections下的集合,也许您会发现一些有趣,而又能帮助解决问题的数据结构。
例如BitArray, BitVector32, CollectionUtils, OrderedCollection, KeyedCollection, ReadOnlyCollection 等等等等