一、设计背景
.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等常用谓词匹配方法。
三、源码
1

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

23
namespace Collections24


{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 SortType36

{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
Value51
}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 SortBy70

{71

get
{ return this.sortBy; }72
set73

{ 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 Count551

{552

get
{ return this.list.Count; }553
}554

555

/**//// <summary>556
/// 获取只读键列表557
/// </summary>558
public ReadOnlyCollection<TKey> Keys559

{560
get561

{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> Values581

{582
get583

{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
get608

{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
set627

{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
get652

{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
set671

{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


浙公网安备 33010602011771号