一、设计背景
.Net Framework自带的类库提供了一些基本的容器类,包括泛型的和非泛型的。其中我们用得最多的可能就是Dictionary<>、List<>(或者Hashtable、ArrayList)了。当我们需要实现的功能比较简单的时候,它们已经够用了,但是更多情况,在使用它们的时候我们还要写一些其实与系统业务没什么关系的代码:涉及多线程编程时需要线程安全地访问它们;有时我们希望容器内的元素按照某种顺序排列;还有些情况下需要把Dictionary<>和List<>结合起来使用,并保证它们的一致性。
二、SafeHashList介绍
SafeHashList<TKey,TValue>内置了Dictionary<TKey,TValue>和List<TKey>,Dictionary<TKey,TValue>用于存放键值对,List<Key>用于保存键的顺序,内部维护了两个容器元素的一致;
支持多线程安全访问;
支持按3种顺序排序:元素添加顺序(默认)、键的顺序(TKey类型须实现IComparable接口)、值的顺序(TValue类型须实现IComparable接口),自动排序并随时可在不同排序方式间切换;
支持Exists、Find、FindAll、FindLast、TrueForAll、ForEach等常用谓词匹配方法。
三、源码

SafeHashList
1
/**//*
2
******************************************************************
3
* 域名空间 :Collections
4
* 类名称 :SafeHashList
5
* 类功能 :线程安全的、保持特定顺序(默认的是添加顺序)的哈希表
6
* 类流程 :
7
* 运用算法 :
8
* 编写人 :Eashion
9
* 编写日期 :2009-7-14
10
* 最近更新日期:2009-11-5
11
* 版 本 :V1.0
12
* 描 述 :2009-9-10 :增加了排序功能,可按3种顺序排序;增加了Exists、Find、FindAll等方法
13
* :2009-11-5 :增加了FindLast、TrueForAll、ForEach方法
14
* 说 明 :使用请注明出处:http://www.cnblogs.com/Eashion
15
* 发现Bug或建议请反馈:Email:eashion08@gmail.com QQ: 27788280
16
* 谢谢!
17
******************************************************************
18
*/
19
using System;
20
using System.Collections.Generic;
21
using System.Collections.ObjectModel;
22
23
namespace Collections
24

{
25
/**//// <summary>
26
/// 线程安全的、保持添加顺序的哈希表
27
/// </summary>
28
/// <typeparam name="TKey">键类型</typeparam>
29
/// <typeparam name="TValue">值类型</typeparam>
30
public class SafeHashList<TKey, TValue>
31
{
32
/**//// <summary>
33
/// 枚举排序的依据类型
34
/// </summary>
35
public enum SortType
36
{
37
/**//// <summary>
38
/// 按添加顺序排序,默认按照此顺序
39
/// </summary>
40
AddOrder = 1,
41
42
/**//// <summary>
43
/// 按键排序,将根据键的IComparable排序
44
/// </summary>
45
Key,
46
47
/**//// <summary>
48
/// 按值排序,将根据值的IComparable排序
49
/// </summary>
50
Value
51
}
52
53
private SortType sortBy;
54
private List<TKey> list;
55
private List<TKey> addingList;
56
private Dictionary<TKey, TValue> dictionary;
57
58
public SafeHashList()
59
{
60
this.sortBy = SafeHashList<TKey, TValue>.SortType.AddOrder;
61
this.list = new List<TKey>();
62
this.addingList = new List<TKey>();
63
this.dictionary = new Dictionary<TKey, TValue>();
64
}
65
66
/**//// <summary>
67
/// 获取或设置 排序的依据
68
/// </summary>
69
public SortType SortBy
70
{
71
get
{ return this.sortBy; }
72
set
73
{
74
lock (this.list)
75
{
76
lock (this.addingList)
77
{
78
lock (this.dictionary)
79
{
80
this.Sort(value);
81
}
82
}
83
}
84
}
85
}
86
87
/**//// <summary>
88
/// 按指定依据排序
89
/// </summary>
90
/// <param name="sortBy">指定排序依据</param>
91
private void Sort(SortType sortBy)
92
{
93
switch (sortBy)
94
{
95
case SafeHashList<TKey, TValue>.SortType.AddOrder:
96
{
97
if (this.sortBy != sortBy)
98
{
99
this.list.Clear();
100
this.list.AddRange(this.addingList);
101
}
102
}
103
break;
104
case SafeHashList<TKey, TValue>.SortType.Key:
105
{
106
this.list.Sort();
107
}
108
break;
109
case SafeHashList<TKey, TValue>.SortType.Value:
110
{
111
this.list.Clear();
112
List<TValue> tmpList = new List<TValue>();
113
Dictionary<TValue, List<TKey>> tmpDictionary = new Dictionary<TValue, List<TKey>>();
114
List<TKey> keyList = null;
115
116
foreach (TKey k in this.addingList)
117
{
118
TValue v = this.dictionary[k];
119
if (!tmpDictionary.ContainsKey(v))
120
{
121
keyList = new List<TKey>();
122
tmpDictionary.Add(v, keyList);
123
tmpList.Add(this.dictionary[k]);
124
}
125
keyList = tmpDictionary[v];
126
keyList.Add(k);
127
}
128
129
tmpList.Sort();
130
foreach (TValue v in tmpList)
131
{
132
keyList = tmpDictionary[v];
133
this.list.AddRange(keyList);
134
}
135
}
136
break;
137
default:
138
break;
139
}
140
141
this.sortBy = sortBy;
142
}
143
144
/**//// <summary>
145
/// 添加一个元素
146
/// </summary>
147
/// <param name="k">键类型</param>
148
/// <param name="v">值类型</param>
149
public void Add(TKey k, TValue v)
150
{
151
if (this.dictionary.ContainsKey(k))
152
throw new Exception("添加的元素主键值已经存在.");
153
154
lock (this.list)
155
{
156
lock (this.addingList)
157
{
158
lock (this.dictionary)
159
{
160
this.dictionary.Add(k, v);
161
this.addingList.Add(k);
162
this.list.Add(k);
163
this.Sort(this.sortBy);
164
}
165
}
166
}
167
}
168
169
/**//// <summary>
170
/// 插入一个元素
171
/// </summary>
172
/// <param name="index">索引</param>
173
/// <param name="k">键类型</param>
174
/// <param name="v">值类型</param>
175
public void Insert(int index, TKey k, TValue v)
176
{
177
if (this.dictionary.ContainsKey(k))
178
throw new Exception("添加的元素主键值已经存在.");
179
180
lock (this.list)
181
{
182
lock (this.addingList)
183
{
184
lock (this.dictionary)
185
{
186
this.dictionary.Add(k, v);
187
this.addingList.Insert(index, k);
188
this.list.Insert(index, k);
189
this.Sort(this.sortBy);
190
}
191
}
192
}
193
}
194
195
/**//// <summary>
196
/// 是否包含某指定的键
197
/// </summary>
198
/// <param name="key"></param>
199
/// <returns></returns>
200
public bool ContainsKey(TKey key)
201
{
202
return this.dictionary.ContainsKey(key);
203
}
204
205
/**//// <summary>
206
/// 是否包含某指定的值
207
/// </summary>
208
/// <param name="value"></param>
209
/// <returns></returns>
210
public bool ContainsValue(TValue value)
211
{
212
return this.dictionary.ContainsValue(value);
213
}
214
215
/**//// <summary>
216
/// 按指定键删除
217
/// </summary>
218
/// <param name="key">指定键</param>
219
public void Remove(TKey key)
220
{
221
if (this.dictionary.ContainsKey(key))
222
{
223
lock (this.list)
224
{
225
lock (this.addingList)
226
{
227
lock (this.dictionary)
228
{
229
this.dictionary.Remove(key);
230
this.addingList.Remove(key);
231
this.list.Remove(key);
232
}
233
}
234
}
235
}
236
}
237
238
/**//// <summary>
239
/// 清除所有元素
240
/// </summary>
241
public void Clear()
242
{
243
lock (this.list)
244
{
245
lock (this.addingList)
246
{
247
lock (this.dictionary)
248
{
249
this.dictionary.Clear();
250
this.addingList.Clear();
251
this.list.Clear();
252
}
253
}
254
}
255
}
256
257
/**//// <summary>
258
/// 搜索与指定谓词所定义的条件相匹配的元素,并返回整个 System.Collections.Generic.List<TKey> 中的第一个匹配元素。
259
/// </summary>
260
/// <param name="match">System.Predicate<TKey> 委托,用于定义要搜索的元素的条件。</param>
261
/// <returns>如果找到与指定谓词定义的条件匹配的第一个元素,则为该元素;否则为类型 TKey 的默认值。</returns>
262
public TKey Find(Predicate<TKey> match)
263
{
264
TKey result = default(TKey);
265
266
lock (this.list)
267
{
268
lock (this.addingList)
269
{
270
lock (this.dictionary)
271
{
272
result = this.list.Find(match);
273
}
274
}
275
}
276
277
return result;
278
}
279
280
/**//// <summary>
281
/// 检索与指定谓词定义的条件匹配的所有元素。
282
/// </summary>
283
/// <param name="match">System.Predicate<TKey> 委托,用于定义要搜索的元素应满足的条件。</param>
284
/// <returns>如果找到,则为一个 System.Collections.Generic.List<TKey>,其中包含与指定谓词所定义的条件相匹配的所有元素;否则为一个空System.Collections.Generic.List<TKey>。</returns>
285
public List<TKey> FindAll(Predicate<TKey> match)
286
{
287
List<TKey> resultList = new List<TKey>();
288
289
lock (this.list)
290
{
291
lock (this.addingList)
292
{
293
lock (this.dictionary)
294
{
295
resultList = this.list.FindAll(match);
296
}
297
}
298
}
299
300
return resultList;
301
}
302
303
/**//// <summary>
304
/// 搜索与指定谓词所定义的条件相匹配的元素,并返回整个 System.Collections.Generic.List<TKey> 中的最后一个匹配元素。
305
/// </summary>
306
/// <param name="match">System.Predicate<TKey> 委托,用于定义要搜索的元素的条件。</param>
307
/// <returns>如果找到与指定谓词定义的条件匹配的最后一个元素,则为该元素;否则为类型 TKey 的默认值。</returns>
308
public TKey FindLast(Predicate<TKey> match)
309
{
310
TKey result = default(TKey);
311
312
lock (this.list)
313
{
314
lock (this.addingList)
315
{
316
lock (this.dictionary)
317
{
318
result = this.list.FindLast(match);
319
}
320
}
321
}
322
323
return result;
324
}
325
326
/**//// <summary>
327
/// 搜索与指定谓词所定义的条件相匹配的元素,并返回整个 System.Collections.Generic.List<TValue> 中的第一个匹配元素。
328
/// </summary>
329
/// <param name="match">System.Predicate<TValue> 委托,用于定义要搜索的元素的条件。</param>
330
/// <returns>如果找到与指定谓词定义的条件匹配的第一个元素,则为该元素;否则为类型 TValue 的默认值。</returns>
331
public TValue Find(Predicate<TValue> match)
332
{
333
TValue result = default(TValue);
334
335
List<TValue> values = new List<TValue>();
336
lock (this.list)
337
{
338
lock (this.addingList)
339
{
340
lock (this.dictionary)
341
{
342
foreach (TKey key in this.list)
343
values.Add(this.dictionary[key]);
344
345
result = values.Find(match);
346
}
347
}
348
}
349
350
return result;
351
}
352
353
/**//// <summary>
354
/// 检索与指定谓词定义的条件匹配的所有元素。
355
/// </summary>
356
/// <param name="match">System.Predicate<TValue> 委托,用于定义要搜索的元素应满足的条件。</param>
357
/// <returns>如果找到,则为一个 System.Collections.Generic.List<TValue>,其中包含与指定谓词所定义的条件相匹配的所有元素;否则为一个空System.Collections.Generic.List<TValue>。</returns>
358
public List<TValue> FindAll(Predicate<TValue> match)
359
{
360
List<TValue> resultList = new List<TValue>();
361
362
List<TValue> values = new List<TValue>();
363
lock (this.list)
364
{
365
lock (this.addingList)
366
{
367
lock (this.dictionary)
368
{
369
foreach (TKey key in this.list)
370
values.Add(this.dictionary[key]);
371
372
resultList = values.FindAll(match);
373
}
374
}
375
}
376
377
return resultList;
378
}
379
380
/**//// <summary>
381
/// 搜索与指定谓词所定义的条件相匹配的元素,并返回整个 System.Collections.Generic.List<TValue> 中的最后一个匹配元素。
382
/// </summary>
383
/// <param name="match">System.Predicate<TValue> 委托,用于定义要搜索的元素的条件。</param>
384
/// <returns>如果找到与指定谓词定义的条件匹配的最后一个元素,则为该元素;否则为类型 TValue 的默认值。</returns>
385
public TValue FindLast(Predicate<TValue> match)
386
{
387
TValue result = default(TValue);
388
389
List<TValue> values = new List<TValue>();
390
lock (this.list)
391
{
392
lock (this.addingList)
393
{
394
lock (this.dictionary)
395
{
396
foreach (TKey key in this.list)
397
values.Add(this.dictionary[key]);
398
399
result = values.FindLast(match);
400
}
401
}
402
}
403
404
return result;
405
}
406
407
/**//// <summary>
408
/// 确定 System.Collections.Generic.List<TKey> 是否包含与指定谓词所定义的条件相匹配的元素。
409
/// </summary>
410
/// <param name="match">System.Predicate<TKey> 委托,用于定义要搜索的元素应满足的条件。</param>
411
/// <returns>如果 System.Collections.Generic.List<TKey> 包含一个或多个与指定谓词所定义的条件相匹配的元素,则为 true;否则为false。</returns>
412
public bool Exists(Predicate<TKey> match)
413
{
414
bool result = false;
415
416
lock (this.list)
417
{
418
lock (this.addingList)
419
{
420
lock (this.dictionary)
421
{
422
result = this.list.Exists(match);
423
}
424
}
425
}
426
427
return result;
428
}
429
430
/**//// <summary>
431
/// 确定是否 System.Collections.Generic.List<TKey> 中的每一个元素都与指定谓词所定义的条件相匹配。
432
/// </summary>
433
/// <param name="match">System.Predicate<TKey> 委托,用于定义要搜索的元素应满足的条件。</param>
434
/// <returns>如果 System.Collections.Generic.List<TKey> 中的每一个元素都与指定谓词所定义的条件相匹配,则为 true;否则为false。</returns>
435
public bool TrueForAll(Predicate<TKey> match)
436
{
437
bool result = false;
438
439
lock (this.list)
440
{
441
lock (this.addingList)
442
{
443
lock (this.dictionary)
444
{
445
result = this.list.TrueForAll(match);
446
}
447
}
448
}
449
450
return result;
451
}
452
453
/**//// <summary>
454
/// 对 System.Collections.Generic.List<TKey> 中的每一个元素执行指定操作
455
/// </summary>
456
/// <param name="action">要对 System.Collections.Generic.List<TKey> 的每个元素执行的 System.Action<TKey> 委托。</param>
457
public void ForEach(Action<TKey> action)
458
{
459
lock (this.list)
460
{
461
lock (this.addingList)
462
{
463
lock (this.dictionary)
464
{
465
this.list.ForEach(action);
466
}
467
}
468
}
469
}
470
471
/**//// <summary>
472
/// 确定 System.Collections.Generic.List<TValue> 是否包含与指定谓词所定义的条件相匹配的元素。
473
/// </summary>
474
/// <param name="match">System.Predicate<TValue> 委托,用于定义要搜索的元素应满足的条件。</param>
475
/// <returns>如果 System.Collections.Generic.List<TValue> 包含一个或多个与指定谓词所定义的条件相匹配的元素,则为 true;否则为false。</returns>
476
public bool Exists(Predicate<TValue> match)
477
{
478
bool result = false;
479
480
List<TValue> values = new List<TValue>();
481
lock (this.list)
482
{
483
lock (this.addingList)
484
{
485
lock (this.dictionary)
486
{
487
foreach (TKey key in this.list)
488
values.Add(this.dictionary[key]);
489
490
result = values.Exists(match);
491
}
492
}
493
}
494
495
return result;
496
}
497
498
/**//// <summary>
499
/// 确定是否 System.Collections.Generic.List<TValue> 中的每一个元素都与指定谓词所定义的条件相匹配。
500
/// </summary>
501
/// <param name="match">System.Predicate<TValue> 委托,用于定义要搜索的元素应满足的条件。</param>
502
/// <returns>如果 System.Collections.Generic.List<TValue> 中的每一个元素都与指定谓词所定义的条件相匹配,则为 true;否则为false。</returns>
503
public bool TrueForAll(Predicate<TValue> match)
504
{
505
bool result = false;
506
507
List<TValue> values = new List<TValue>();
508
lock (this.list)
509
{
510
lock (this.addingList)
511
{
512
lock (this.dictionary)
513
{
514
foreach (TKey key in this.list)
515
values.Add(this.dictionary[key]);
516
517
result = values.TrueForAll(match);
518
}
519
}
520
}
521
522
return result;
523
}
524
525
/**//// <summary>
526
/// 对 System.Collections.Generic.List<TValue> 中的每一个元素执行指定操作
527
/// </summary>
528
/// <param name="action">要对 System.Collections.Generic.List<TValue> 的每个元素执行的 System.Action<TValue> 委托。</param>
529
public void ForEach(Action<TValue> action)
530
{
531
List<TValue> values = new List<TValue>();
532
lock (this.list)
533
{
534
lock (this.addingList)
535
{
536
lock (this.dictionary)
537
{
538
foreach (TKey key in this.list)
539
values.Add(this.dictionary[key]);
540
541
values.ForEach(action);
542
}
543
}
544
}
545
}
546
547
/**//// <summary>
548
/// 获取当前元素个数
549
/// </summary>
550
public int Count
551
{
552
get
{ return this.list.Count; }
553
}
554
555
/**//// <summary>
556
/// 获取只读键列表
557
/// </summary>
558
public ReadOnlyCollection<TKey> Keys
559
{
560
get
561
{
562
ReadOnlyCollection<TKey> collection = null;
563
lock (this.list)
564
{
565
lock (this.addingList)
566
{
567
lock (this.dictionary)
568
{
569
collection = this.list.AsReadOnly();
570
}
571
}
572
}
573
return collection;
574
}
575
}
576
577
/**//// <summary>
578
/// 获取值列表
579
/// </summary>
580
public List<TValue> Values
581
{
582
get
583
{
584
List<TValue> values = new List<TValue>();
585
lock (this.list)
586
{
587
lock (this.addingList)
588
{
589
lock (this.dictionary)
590
{
591
foreach (TKey key in this.list)
592
values.Add(this.dictionary[key]);
593
}
594
}
595
}
596
return values;
597
}
598
}
599
600
/**//// <summary>
601
/// 获取或设置 索引器
602
/// </summary>
603
/// <param name="key">键</param>
604
/// <returns>值</returns>
605
public TValue this[TKey key]
606
{
607
get
608
{
609
if (!this.dictionary.ContainsKey(key))
610
throw new Exception("指定的主键值不存在。");
611
612
TValue value = default(TValue);
613
lock (this.list)
614
{
615
lock (this.addingList)
616
{
617
lock (this.dictionary)
618
{
619
value = this.dictionary[key];
620
}
621
}
622
}
623
624
return value;
625
}
626
set
627
{
628
if (!this.dictionary.ContainsKey(key))
629
throw new Exception("指定的主键值不存在。");
630
631
lock (this.list)
632
{
633
lock (this.addingList)
634
{
635
lock (this.dictionary)
636
{
637
this.dictionary[key] = value;
638
}
639
}
640
}
641
}
642
}
643
644
/**//// <summary>
645
/// 获取或设置 索引器
646
/// </summary>
647
/// <param name="index">键索引</param>
648
/// <returns>值</returns>
649
public TValue this[int index]
650
{
651
get
652
{
653
if (this.list.Count <= index)
654
throw new Exception("索引值超出了范围。");
655
656
TValue value = default(TValue);
657
lock (this.list)
658
{
659
lock (this.addingList)
660
{
661
lock (this.dictionary)
662
{
663
value = this.dictionary[this.list[index]];
664
}
665
}
666
}
667
668
return value;
669
}
670
set
671
{
672
if (this.list.Count <= index)
673
throw new Exception("索引值超出了范围。");
674
675
lock (this.list)
676
{
677
lock (this.addingList)
678
{
679
lock (this.dictionary)
680
{
681
this.dictionary[this.list[index]] = value;
682
}
683
}
684
}
685
}
686
}
687
}
688
}
689