|
使用过Java的朋友,应该知道它有个超好用的HashMap容器类,面试必问的,在Delphi10中有TDictionary类,但Delphi7没得用,所以自己动手,使用数组 + 链表写个类似Java的HashMap类,提供给所有坚守Delphi的朋友们,性能还是相当不错的。
1 {*******************************************************}
2 { }
3 { Delphi HashMap }
4 { }
5 { 版权所有 (C) 2018 hsoft }
6 { }
7 { }
8 { Author: MarkWu Email: 77910086@qq.com }
9 { Date: 2018-01-02 14:17:00 }
10 { Desc: HashMap }
11 {*******************************************************}
12
13 unit uHashMap;
14
15 interface
16
17 uses
18 Windows, SysUtils, StrUtils, Classes, uHashEntry, Variants;
19
20 type
21 // 实体数组类型
22 TEntrySet = array of THashEntry;
23
24 // 排序类型
25 TSortType = (
26 stKey, // 按Key排序
27 stValue, // 按Value排序
28 stKeyValue // Key=Value排序
29 );
30
31 THashMap = class
32 private
33 // 临界值
34 FThreshold: Integer;
35
36 // 元素个数
37 FCount: Integer;
38
39 // 扩容次数
40 FResize: Integer;
41
42 FTable: TEntrySet;
43
44 procedure InitTable();
45
46 // 计算AKey的HashCode
47 function HashCode(AKey: string): Integer;
48 function IndexOf(AKey: string; iLen: Integer = 0): Integer;
49
50 procedure Put(AIndex: Integer; AKey: string; AValue: Variant; AIsObj: Boolean = False);
51 // 加入Key为空
52 procedure PutNullKey(AValue: Variant);
53
54 procedure Resize(capacity: Integer);
55
56 function ToList: TList;
57
58 //扩容时重新计算各元素的index
59 procedure Transfer(ANewTable: TEntrySet);
60 function GetItems(Index: Integer): THashEntry;
61
62 public
63 constructor Create();
64 destructor Destroy; override;
65 // 添加一个元素
66 procedure Add(AKey: string; AValue: Variant; AIsObj: Boolean = False); overload;
67 procedure Add(AMap: THashMap); overload;
68 procedure AddObject(AKey: string; AValue: TObject);
69
70 function Get(AKey: string): Variant;
71 function GetObject(AKey: string): TObject;
72 function GetNullKey: Variant;
73 function GetEntry(AKey: string): THashEntry;
74 procedure Remove(AKey: string);
75 function ContainsKey(AKey: string): Boolean;
76 procedure Clear;
77
78 function GetEntrySet: TEntrySet;
79
80 function ToString: string;
81
82 // 排序
83 function Sort(ASortType: TSortType = stKeyValue): TEntrySet;
84
85 property Count: Integer read FCount;
86 property Items[Index: Integer]: THashEntry read GetItems; default;
87 end;
88
89 implementation
90
91
92 const
93 //默认初始化大小 16, 数组长度一定是2的次幂
94 DEFAULT_INITIAL_CAPACITY = 16;
95
96 //默认负载因子 0.75
97 DEFAULT_LOAD_FACTOR = 0.75;
98
99 MAX_SIZE = 1000000;
100
101 { THashMap }
102
103 constructor THashMap.Create;
104 begin
105 InitTable;
106 end;
107
108 destructor THashMap.Destroy;
109 begin
110 Clear;
111
112 SetLength(FTable, 0);
113 FCount := 0;
114 inherited;
115 end;
116
117
118 procedure THashMap.InitTable;
119 begin
120 SetLength(FTable, DEFAULT_INITIAL_CAPACITY);
121 FThreshold := Trunc(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
122 FCount := 0;
123 end;
124
125 // 计算AKey的HashCode
126 function THashMap.HashCode(AKey: string): Integer;
127 var
128 I: Integer;
129 begin
130 Result := 0;
131 if (Result = 0) and (Length(AKey) > 0) then
132 begin
133 for I := 1 to Length(AKey) do
134 begin
135 Result := 31 * Result + Ord(AKey[I]);
136 end;
137 end;
138 end;
139
140 function THashMap.IndexOf(AKey: string; iLen: Integer): Integer;
141 begin
142 if iLen = 0 then iLen := Length(FTable);
143 // 根据key的hashcode和table长度取模计算key在table中的位置
144 Result := HashCode(AKey) and (iLen - 1);
145 end;
146
147 procedure THashMap.Add(AKey: string; AValue: Variant; AIsObj: Boolean);
148 var
149 index: Integer;
150 entry: THashEntry;
151 begin
152 // key为''时,需要特殊处理
153 if AKey = '' then
154 begin
155 PutNullKey(AValue);
156 Exit;
157 end;
158
159 if Length(FTable) = 0 then
160 InitTable;
161
162 index := IndexOf(AKey);
163 // 遍历index位置的Entry, 若找到重复key,则更新对应entry的值,再返回
164 entry := FTable[index];
165 while entry <> nil do
166 begin
167 if (HashCode(entry.Key) = HashCode(AKey)) and (SameText(entry.Key, AKey)) then
168 begin
169 //entry.Value := Unassigned;
170 entry.Value := AValue;
171 Exit;
172 end;
173 entry := entry.Next;
174 end;
175 // 如果index位置没有找到或者未找到重复的Key, 则将新Key添加到table的index位置
176 Put(index, AKey, AValue, AIsObj);
177 end;
178
179 procedure THashMap.PutNullKey(AValue: Variant);
180 var
181 entry: THashEntry;
182 begin
183 entry := FTable[0];
184 while entry <> nil do
185 begin
186 // 如果找到Key为空的对象时,则覆盖它
187 if entry.Key = '' then
188 begin
189 entry.Value := AValue;
190 Exit;
191 end;
192
193 entry := entry.Next;
194 end;
195 Put(0, '', AValue);
196 end;
197
198 procedure THashMap.Put(AIndex: Integer; AKey: string; AValue: Variant; AIsObj: Boolean = False);
199 var
200 entry: THashEntry;
201 begin
202 // 将新的entry放到table的index位置第一个, 如果原来有值则以链表存放
203 entry := THashEntry.Create(AKey, AValue, FTable[AIndex], AIsObj);
204 FTable[AIndex] := entry;
205 // 若达到临界值, 则进行扩容,将table的capacity翻倍
206 Inc(FCount);
207
208 if FThreshold >= MAX_SIZE then
209 begin
210 FThreshold := MAX_SIZE;
211 Exit;
212 end;
213
214 if FCount >= FThreshold then
215 begin
216 Resize(Length(FTable) * 2);
217 end;
218 end;
219
220 procedure THashMap.Resize(capacity: Integer);
221 var
222 I, index: Integer;
223 newTable: TEntrySet;
224 begin
225 if capacity <= Length(FTable) then Exit;
226
227
228 SetLength(newTable, capacity);
229
230 Transfer(newTable);
231 FTable := nil;
232 FTable := newTable;
233
234 //修改临界值
235 FThreshold := Trunc(Length(FTable) * DEFAULT_LOAD_FACTOR);
236 Inc(FResize);
237 end;
238
239 //重新计算index
240 procedure THashMap.Transfer(ANewTable: TEntrySet);
241 var
242 I, newIndex: Integer;
243 iNewCapacity: Integer;
244 e, tmpNext: THashEntry;
245 begin
246 iNewCapacity := Length(ANewTable);
247 // 循环Table,重新计算各元素索引位置, 再把旧数组数据Copy到新数组中
248 for I := Low(FTable) to High(FTable) do
249 begin
250 e := FTable[I];
251 while e <> nil do
252 begin
253 tmpNext := e.Next;
254 // 计算出新的索引
255 newIndex := IndexOf(e.Key, iNewCapacity);
256 // 把当前旧entry.next链指向新的索引位置,ANewTable[newIndex]可能为nil, 也可能是entry链,
257 // 如果是entry链,就直接在链表头插入
258 e.Next := ANewTable[newIndex];
259 ANewTable[newIndex] := e;
260
261 e := tmpNext;
262 end;
263 end;
264 end;
265
266 function THashMap.Get(AKey: string): Variant;
267 var
268 entry: THashEntry;
269 begin
270 Result := NULL;
271 if (AKey = '') then
272 begin
273 Result := GetNullKey;
274 Exit;
275 end;
276
277 entry := GetEntry(AKey);
278 if entry = nil then
279 Result := NULL
280 else
281 Result := entry.Value;
282 end;
283
284 function THashMap.GetNullKey: Variant;
285 var
286 e: THashEntry;
287 begin
288 if FCount = 0 then
289 begin
290 Result := Null;
291 Exit;
292 end;
293
294 //在FTable[0]的链表上查找key为''的键值对,因为''默认是存在FTable[0]的桶里
295 e := FTable[0];
296 while e <> nil do
297 begin
298 if e.Key = '' then
299 begin
300 Result := e.Value;
301 Break;
302 end;
303 e := e.Next;
304 end;
305 end;
306
307
308 function THashMap.GetEntry(AKey: string): THashEntry;
309 var
310 entry: THashEntry;
311 begin
312 entry := FTable[IndexOf(AKey)];
313 try
314 while (entry <> nil) do
315 begin
316 if (HashCode(entry.Key) = HashCode(AKey)) and SameText(entry.Key, AKey) then
317 begin
318 Result := entry;
319 Exit;
320 end;
321 entry := entry.Next;
322 end;
323 Result := entry;
324 except
325 Result := nil;
326 end;
327 end;
328
329 procedure THashMap.Remove(AKey: string);
330 var
331 index: Integer;
332 pre, entry: THashEntry;
333 begin
334 if AKey = '' then Exit;
335
336 index := IndexOf(AKey);
337 pre := nil;
338 entry := FTable[index];
339 while entry <> nil do
340 begin
341 if (HashCode(entry.Key) = HashCode(AKey)) and SameText(entry.Key, AKey) then
342 begin
343 if pre = nil then
344 FTable[index] := entry.Next
345 else
346 pre.Next := entry.Next;
347
348 Dec(FCount);
349 Exit;
350 end;
351 pre := entry;
352 entry := entry.Next;
353 end;
354 end;
355
356
357 function THashMap.ContainsKey(AKey: string): Boolean;
358 begin
359 Result := False;
360 if AKey = '' then Exit;
361 Result := GetEntry(aKey) <> nil;
362 end;
363
364 procedure THashMap.Clear;
365 var
366 I: Integer;
367 firstEntry, pre, Entry: THashEntry;
368 begin
369 for I := 0 to Length(FTable) - 1 do
370 begin
371 firstEntry := FTable[I];
372 if firstEntry <> nil then
373 begin
374 // 有链表
375 pre := nil;
376 entry := firstEntry.Next;
377 while entry <> nil do
378 begin
379 pre := Entry;
380 Entry := pre.Next;
381 pre.Next := nil;
382 FreeAndNil(pre);
383 end;
384 FreeAndNil(firstEntry);
385 FTable[I] := nil;
386 end;
387 end;
388
389 SetLength(FTable, 0);
390 FCount := 0;
391 end;
392
393 function THashMap.ToString(): string;
394 var
395 I, iPadLeft: Integer;
396 entry: THashEntry;
397 sValue: string;
398 begin
399 if not Assigned(FTable) then Exit;
400 Result := Format('Size: %d, capacity: %d, Resize: %d;'#10#13, [FCount, Length(FTable), FResize]);
401 Result := Result + #13#10;
402 for I := 0 to Length(FTable) - 1 do
403 begin
404 entry := FTable[I];
405 if entry = nil then
406 Result := Result + Format('a[%d] = nil'#13#10, [I])
407 else
408 Result := Result + Format('a[%d] ', [I]);
409
410 iPadLeft := Length(Format('a[%d] ', [I])) + 1;
411 while entry <> nil do
412 begin
413 case TVarData(entry.Value).VType of
414 varString: sValue := '''' + entry.Value + '''';
415 else
416 sValue := VarToStrDef(entry.Value, '');
417 end;
418
419
420 if entry <> FTable[I] then
421 Result := Result + DupeString(' ', iPadLeft) + ' -> ' + entry.Key + ' = ' + sValue
422 else
423 Result := Result + entry.Key + ' = ' + sValue;
424
425 entry := entry.Next;
426 Result := Result + #13#10;
427 end;
428 end;
429 end;
430
431 function THashMap.ToList: TList;
432 var
433 I: Integer;
434 e: THashEntry;
435 begin
436 Result := nil;
437 if Length(FTable) = 0 then
438 begin
439 Exit;
440 end;
441
442 Result := TList.Create;
443 for I := Low(FTable) to High(FTable) do
444 begin
445 e := FTable[I];
446 while e <> nil do
447 begin
448 Result.Add(e);
449 e := e.Next;
450 end;
451 end;
452 end;
453
454 function THashMap.GetEntrySet: TEntrySet;
455 var
456 I: Integer;
457 e: THashEntry;
458 aList: TList;
459 begin
460 Result := nil;
461 if Length(FTable) = 0 then
462 begin
463 Exit;
464 end;
465
466 try
467 // 1、先获取到数组和链表中所有Entry对象
468 aList := ToList;
469 // 2、把得到的Entry对象加入到TEntrySet中
470 SetLength(Result, aList.Count);
471 for I := 0 to aList.Count - 1 do
472 begin
473 Result[I] := aList[I];
474 end;
475 finally
476 FreeAndNil(aList);
477 end;
478 end;
479
480 procedure THashMap.Add(AMap: THashMap);
481 var
482 I: Integer;
483 e: THashEntry;
484 aSet: TEntrySet;
485 begin
486 aSet := AMap.GetEntrySet;
487 for I := 0 to Length(aSet) - 1 do
488 begin
489 Add(aSet[I].Key, aSet[I].Value);
490 end;
491 end;
492
493 // 插入对象
494 procedure THashMap.AddObject(AKey: string; AValue: TObject);
495 begin
496 Add(AKey, Integer(AValue), True);
497 end;
498
499 function THashMap.GetObject(AKey: string): TObject;
500 begin
501 Result := TObject(Integer(Get(AKey)));
502 end;
503
504
505 // key排序
506 function SortCompareByKey(Item1, Item2: Pointer): Integer;
507 begin
508 Result := AnsiCompareStr(THashEntry(item1).Key, THashEntry(Item2).Key);
509 end;
510
511 // Value排序
512 function SortCompareByValue(Item1, Item2: Pointer): Integer;
513 begin
514 Result := AnsiCompareStr(THashEntry(item1).Value, THashEntry(Item2).Value);
515 end;
516
517 // KeyValue排序
518 function SortCompareByKeyValue(Item1, Item2: Pointer): Integer;
519 begin
520 Result := AnsiCompareStr(THashEntry(item1).Key + VarToStrDef(THashEntry(item1).Value, '')
521 , THashEntry(item2).Key + VarToStrDef(THashEntry(Item2).Value, ''));
522 end;
523
524 function THashMap.Sort(ASortType: TSortType): TEntrySet;
525 var
526 I: Integer;
527 aSortCompare: TListSortCompare;
528 aList: TList;
529 begin
530 aList := ToList;
531 try
532 case ASortType of
533 stKey:
534 aSortCompare := SortCompareByKey;
535 stValue:
536 aSortCompare := SortCompareByValue;
537 else
538 aSortCompare := SortCompareByKeyValue;
539 end;
540 aList.Sort(aSortCompare);
541
542 SetLength(Result, aList.Count);
543 for I := 0 to aList.Count - 1 do
544 begin
545 Result[I] := aList[I];
546 end;
547 finally
548 FreeAndNil(aList);
549 end;
550 end;
551
552
553
554 function THashMap.GetItems(Index: Integer): THashEntry;
555 begin
556 if (Index < 0) or (Index >= FCount) then
557 begin
558 Result := nil;
559 Exit;
560 end;
561 Result := FTable[Index];
562 end;
563
564 end.
1 {*******************************************************}
2 { }
3 { Delphi HashMap }
4 { }
5 { 版权所有 (C) 2018 hsoft }
6 { }
7 { }
8 { Author: MarkWu Email: 77910086@qq.com }
9 { Date: 2018-01-02 14:17:00 }
10 { Desc: HashMap }
11 {*******************************************************}
12
13 unit uHashEntry;
14
15 interface
16
17 uses
18 Variants;
19
20 type
21 THashEntry = class
22 private
23 FKey: string;
24 FValue: Variant;
25 FNext: THashEntry;
26 FIsObj: Boolean;
27 procedure SetValue(const Value: Variant);
28 function GetValue: Variant;
29 public
30 constructor Create(AKey: string; AValue: Variant; ANext: THashEntry; AIsObj: Boolean = False);
31
32 function ToString(): string;
33 function HashCode: Integer;
34
35 property Key: string read FKey write FKey;
36 property Value: Variant read GetValue write SetValue;
37 property Next: THashEntry read FNext write FNext;
38 property IsObj: Boolean read FIsObj;
39 end;
40
41 implementation
42
43 { THashEntry }
44
45 constructor THashEntry.Create(AKey: string; AValue: Variant; ANext: THashEntry; AIsObj: Boolean);
46 begin
47 FKey := AKey;
48 FValue := AValue;
49 FIsObj := AIsObj;
50 FNext := ANext;
51 end;
52
53 function THashEntry.HashCode: Integer;
54 begin
55 Result := Integer(Self);
56 end;
57
58 function THashEntry.GetValue: Variant;
59 begin
60 Result := FValue;
61 end;
62
63 procedure THashEntry.SetValue(const Value: Variant);
64 begin
65 FValue := Value;
66 end;
67
68 function THashEntry.ToString: string;
69 begin
70 Result := FKey + '=' + VarToStrDef(FValue, '');
71 end;
72
73 end.
测试效果图
HashMap, StringList, HashedStringList的性能比较, HashMap的性能比较稳定,保持O(1), 而HashedStringList第1次查找时很慢,后面就稳定了,不知啥原因,没有去跟踪它代码。
测试程序源码:
object Form1: TForm1
Left = 263
Top = 169
Width = 787
Height = 518
Caption = 'HashMap Demo -- Author: MarkWu QQ:77910086'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 237
Top = 90
Width = 18
Height = 13
Caption = 'Key'
end
object Label2: TLabel
Left = 237
Top = 119
Width = 27
Height = 13
Caption = 'Value'
end
object Label3: TLabel
Left = 231
Top = 168
Width = 34
Height = 13
Caption = 'Serach'
end
object Label4: TLabel
Left = 240
Top = 348
Width = 14
Height = 13
Caption = 'N: '
end
object Label5: TLabel
Left = 365
Top = 347
Width = 17
Height = 13
Caption = 'Get'
end
object Button1: TButton
Left = 257
Top = 11
Width = 75
Height = 25
Caption = #21021#22987#21270'Map'
TabOrder = 2
OnClick = Button1Click
end
object Memo1: TMemo
Left = 0
Top = 0
Width = 225
Height = 480
Align = alLeft
ScrollBars = ssVertical
TabOrder = 0
end
object Button2: TButton
Left = 364
Top = 163
Width = 75
Height = 25
Caption = 'Get'
TabOrder = 8
OnClick = Button2Click
end
object Edit1: TEdit
Left = 268
Top = 164
Width = 85
Height = 21
TabOrder = 9
end
object Button3: TButton
Left = 364
Top = 97
Width = 75
Height = 25
Caption = 'Put'
TabOrder = 6
OnClick = Button3Click
end
object edt_key: TEdit
Left = 268
Top = 85
Width = 85
Height = 21
TabOrder = 5
end
object edt_value: TEdit
Left = 268
Top = 117
Width = 85
Height = 21
TabOrder = 7
end
object Button4: TButton
Left = 364
Top = 11
Width = 75
Height = 25
Caption = 'Destory Map'
TabOrder = 3
OnClick = Button4Click
end
object btnSortKey: TButton
Left = 241
Top = 236
Width = 97
Height = 25
Caption = 'Sort Key'
TabOrder = 12
OnClick = btnSortKeyClick
end
object PutMap: TButton
Left = 241
Top = 203
Width = 97
Height = 25
Caption = 'PutMap'
TabOrder = 10
OnClick = PutMapClick
end
object Button5: TButton
Left = 257
Top = 51
Width = 184
Height = 25
Caption = #25171#21360'Map'#20869#23481
TabOrder = 4
OnClick = Button5Click
end
object btnSortValue: TButton
Left = 241
Top = 270
Width = 97
Height = 25
Caption = 'Sort Value'
TabOrder = 13
OnClick = btnSortValueClick
end
object btnSortKeyValue: TButton
Left = 241
Top = 303
Width = 97
Height = 25
Caption = 'Sort KeyValue'
TabOrder = 14
OnClick = btnSortKeyValueClick
end
object btnHashMap10000: TButton
Left = 241
Top = 379
Width = 122
Height = 25
Caption = 'HashMap '#22686#21152'N'#26465
TabOrder = 17
OnClick = btnHashMap10000Click
end
object btnStringList10000: TButton
Left = 241
Top = 408
Width = 122
Height = 25
Caption = 'StringList '#22686#21152'N'#26465
TabOrder = 19
OnClick = btnStringList10000Click
end
object edt_N: TEdit
Left = 259
Top = 345
Width = 104
Height = 21
TabOrder = 15
Text = '10000'
end
object btn_hashMap_get: TButton
Left = 373
Top = 379
Width = 100
Height = 25
Caption = 'hashMap_get'
TabOrder = 18
OnClick = btn_hashMap_getClick
end
object btn_stringList_get: TButton
Left = 373
Top = 408
Width = 100
Height = 25
Caption = 'stringList_get'
TabOrder = 20
OnClick = btn_stringList_getClick
end
object edt_Get: TEdit
Left = 387
Top = 345
Width = 104
Height = 21
TabOrder = 16
end
object Button6: TButton
Left = 364
Top = 203
Width = 75
Height = 25
Caption = 'AddObject'
TabOrder = 11
OnClick = Button6Click
end
object Panel1: TPanel
Left = 504
Top = 0
Width = 267
Height = 480
Align = alRight
BevelOuter = bvNone
TabOrder = 1
object Label6: TLabel
Left = 0
Top = 0
Width = 267
Height = 16
Align = alTop
Caption = 'HashMap'#20869#23384#20998#24067
end
object Memo2: TMemo
Left = 0
Top = 16
Width = 267
Height = 464
Align = alClient
ScrollBars = ssVertical
TabOrder = 0
end
end
object btn_HashStringList1000: TButton
Left = 241
Top = 439
Width = 122
Height = 25
Caption = 'HashStringList '#22686#21152'N'#26465
TabOrder = 21
OnClick = btn_HashStringList1000Click
end
object btn_HashStringList_get: TButton
Left = 373
Top = 439
Width = 100
Height = 25
Caption = 'HashStringList_Get'
TabOrder = 22
OnClick = btn_HashStringList_getClick
end
end
{*******************************************************}
{ }
{ Delphi HashMap test }
{ }
{ 版权所有 (C) 2018 hsoft }
{ }
{ }
{ Author: MarkWu Email: 77910086@qq.com }
{ Date: 2018-01-02 14:17:00 }
{ Desc: HashMap }
{*******************************************************}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, uHashMap, StdCtrls, StrUtils, ExtCtrls, IniFiles;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
Edit1: TEdit;
Button3: TButton;
edt_key: TEdit;
edt_value: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Button4: TButton;
btnSortKey: TButton;
PutMap: TButton;
Button5: TButton;
btnSortValue: TButton;
btnSortKeyValue: TButton;
btnHashMap10000: TButton;
btnStringList10000: TButton;
Label4: TLabel;
edt_N: TEdit;
btn_hashMap_get: TButton;
btn_stringList_get: TButton;
Label5: TLabel;
edt_Get: TEdit;
Button6: TButton;
Panel1: TPanel;
Label6: TLabel;
Memo2: TMemo;
btn_HashStringList1000: TButton;
btn_HashStringList_get: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure btnSortKeyClick(Sender: TObject);
procedure PutMapClick(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure btnSortValueClick(Sender: TObject);
procedure btnSortKeyValueClick(Sender: TObject);
procedure btnHashMap10000Click(Sender: TObject);
procedure btnStringList10000Click(Sender: TObject);
procedure btn_hashMap_getClick(Sender: TObject);
procedure btn_stringList_getClick(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure btn_HashStringList1000Click(Sender: TObject);
procedure btn_HashStringList_getClick(Sender: TObject);
private
{ Private declarations }
aHashMap: THashMap;
FMap: THashMap;
FList: TStringList;
FHashList: THashedStringList;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses uHashEntry;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
aHashMap := THashMap.Create;
FMap := THashMap.Create;
FList := TStringList.Create;
FHashList := THashedStringList.Create;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
//caption := IntToStr(aHashMap.HashCode('123'));
//caption := IntToStr(5 mod 3);
aHashMap.Add('中国', '中华人民共和国');
aHashMap.Add('中國', '中華人民共和國');
aHashMap.Add('吴wu', 'MarkWu');
aHashMap.Add('b', 2);
aHashMap.Add('c', 3);
aHashMap.Add('d', 'dd');
aHashMap.Add('e', 'ee');
aHashMap.Add('f', 'ff');
aHashMap.Add('g', 'ggg');
aHashMap.Add('h', 11.1);
aHashMap.Add('i', 22.2);
aHashMap.Add('j', 33.3);
aHashMap.Add('k', 44.4);
aHashMap.Add('l', True);
aHashMap.Add('aa', 'a1');
aHashMap.Add('ca', 'c2');
aHashMap.Add('', '0000000000');
aHashMap.Add('', '1111111111');
// aHashMap.Put('m', VarArrayOf([1, 2, 'a', 'b']));
Memo1.Lines.Add(aHashMap.ToString);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
I: Integer;
aMap: THashMap;
aSet: TEntrySet;
begin
{ aMap := THashMap.Create;
aMap.Put('h1', 'h1');
aMap.Put('h2', 2);
aMap.Put('h3', 33);
aMap.Put('中1', 81);
aMap.Put('中2', 82);
aMap.Put('中2', 83);
aMap.Put(aHashMap);
}
//Memo2.Lines.Add(aMap.ToString);
Memo2.Lines.Add('---------------Get-----------------');
Memo2.Lines.Add(VarToStrDef( aHashMap.Get(Edit1.Text), ''));
//aMap.Free;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
aHashMap.Add(edt_key.Text, edt_value.Text);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
FreeAndNil(aHashMap);
end;
procedure TForm1.btnSortKeyClick(Sender: TObject);
var
I: Integer;
aSet: TEntrySet;
begin
Memo2.Lines.Add('---------------Sort Key-----------------');
aSet := aHashMap.Sort(stKey);
for I := 0 to Length(aSet) - 1 do
begin
Memo2.Lines.Add(aSet[I].Key + '=' + VarToStrDef(aSet[I].Value, 'NULL') );
end;
end;
procedure TForm1.btnSortValueClick(Sender: TObject);
var
I: Integer;
aSet: TEntrySet;
begin
Memo2.Lines.Add('---------------Sort Value-----------------');
aSet := aHashMap.Sort(stValue);
for I := 0 to Length(aSet) - 1 do
begin
Memo2.Lines.Add(aSet[I].Key + '=' + VarToStrDef(aSet[I].Value, 'NULL') );
end;
end;
procedure TForm1.btnSortKeyValueClick(Sender: TObject);
var
I: Integer;
aSet: TEntrySet;
begin
Memo2.Lines.Add('---------------Sort KeyValue-----------------');
aSet := aHashMap.Sort(stKeyValue);
for I := 0 to Length(aSet) - 1 do
begin
Memo2.Lines.Add(aSet[I].Key + '=' + VarToStrDef(aSet[I].Value, 'NULL') );
end;
end;
procedure TForm1.PutMapClick(Sender: TObject);
var
I: Integer;
aMap: THashMap;
aSet: TEntrySet;
begin
aMap := THashMap.Create;
aMap.Add('h1', 'h1');
aMap.Add('h2', 2);
aMap.Add('h3', 33);
aMap.Add('中1', 81);
aMap.Add('中2', 82);
aMap.Add('中2', 83);
//aMap.Put(aHashMap);
aHashMap.Add(aMap);
//Memo2.Lines.Add(aMap.ToString);
Memo2.Lines.Add('-------------------PutMap-------------------');
aSet := aHashMap.GetEntrySet;
for I := 0 to Length(aSet) - 1 do
begin
Memo2.Lines.Add(aSet[I].Key + '=' + VarToStrDef(aSet[I].Value, '') );
end;
aMap.Free;
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
Memo2.Lines.Add('------------------ToString----------------------');
Memo2.Lines.Add(aHashMap.ToString);
end;
procedure TForm1.btnHashMap10000Click(Sender: TObject);
var
I: Integer;
iBegin, iEnd: Cardinal;
map: THashMap;
begin
FMap.Clear;
iBegin := GetTickCount;
map := FMap;
for I := 0 to StrToInt(edt_N.Text) - 1 do
begin
map.Add( IntToStr(I), I); //'m' +
end;
iEnd := (GetTickCount - iBegin);
Memo2.Lines.Add(Format('-------------------- %s ToString--------------------', [btnHashMap10000.Caption]));
Memo2.Lines.Add(Format('HashMap 增加%d条, 总共花了%d ms', [StrToIntDef(edt_N.Text, 1), iEnd]));
//Memo2.Lines.Add(map.ToString);
end;
procedure TForm1.btnStringList10000Click(Sender: TObject);
var
I: Integer;
iBegin, iEnd: Cardinal;
str: string;
aList: TStringList;
begin
FList.Clear;
iBegin := GetTickCount;
aList := FList; //TStringList.Create;
for I := 0 to StrToInt(edt_N.Text) -1 do
begin
aList.Add( IntToStr(I) + '=' + IntToStr(I));
end;
iEnd := GetTickCount - iBegin;
Memo2.Lines.Add(Format('-------------------- %s ToString--------------------', [btnStringList10000.Caption]));
//Memo2.Lines.Add(btnStringList10000.Caption + ' 总共花了' + Inttostr(iEnd));
Memo2.Lines.Add(Format('StringList 增加%d条, 总共花了%d ms', [StrToIntDef(edt_N.Text, 1), iEnd]));
{
str := '';
for I := 0 to aList.Count - 1 do
begin
str := str + #13#10 + aList[I];
end;
Memo2.Lines.Add(str);
}
end;
procedure TForm1.btn_hashMap_getClick(Sender: TObject);
var
iBegin, iEnd: Cardinal;
sValue: string;
begin
try
if Trim(edt_Get.Text) = '' then
begin
if edt_Get.CanFocus then edt_Get.SetFocus;
ShowMessage('请输入要查询的key');
Abort;
end;
iBegin := GetTickCount;
sValue := FMap.Get(edt_Get.Text);
iEnd := GetTickCount - iBegin;
Memo2.Lines.Add('------------------hashMap Get-----------------');
Memo2.Lines.Add(sValue + '--->' + IntToStr(iEnd) + 'ms');
except
end;
end;
procedure TForm1.btn_stringList_getClick(Sender: TObject);
var
iBegin, iEnd: Cardinal;
sValue: string;
begin
try
if Trim(edt_Get.Text) = '' then
begin
if edt_Get.CanFocus then edt_Get.SetFocus;
ShowMessage('请输入要查询的key');
Abort;
end;
iBegin := GetTickCount;
sValue := FList.Values[edt_Get.Text]; //FList.ValueFromIndex(Flist.);
iEnd := GetTickCount - iBegin;
Memo2.Lines.Add('------------------StringList Get-----------------');
Memo2.Lines.Add(sValue + '--->' + IntToStr(iEnd) + 'ms');
except
end;
end;
procedure TForm1.Button6Click(Sender: TObject);
var
v: Variant;
map: THashMap;
begin
//map := THashMap.Create;
map := aHashMap;
try
v := Integer(Self);
map.AddObject('form1', Self);
//ShowMessage(map.Get('form1').Value);
ShowMessage(TForm1(map.GetObject('form1')).Caption);
finally
//FreeAndNil(map);
end;
end;
procedure TForm1.btn_HashStringList1000Click(Sender: TObject);
var
I: Integer;
iBegin, iEnd: Cardinal;
str: string;
aList: THashedStringList;
begin
FHashList.Clear;
iBegin := GetTickCount;
aList := FHashList; //TStringList.Create;
for I := 0 to StrToInt(edt_N.Text) -1 do
begin
aList.Add(IntToStr(I) + '=' + IntToStr(I));
end;
iEnd := GetTickCount - iBegin;
Memo2.Lines.Add(Format('-------------------- %s ToString--------------------', [btn_HashStringList1000.Caption]));
//Memo2.Lines.Add(btnStringList10000.Caption + ' 总共花了' + Inttostr(iEnd));
Memo2.Lines.Add(Format('HashStringList 增加%d条, 总共花了%d ms', [StrToIntDef(edt_N.Text, 1), iEnd]));
{
str := '';
for I := 0 to aList.Count - 1 do
begin
str := str + #13#10 + aList[I];
end;
Memo2.Lines.Add(str);
}
end;
procedure TForm1.btn_HashStringList_getClick(Sender: TObject);
var
iBegin, iEnd: Cardinal;
sValue: string;
begin
try
if Trim(edt_Get.Text) = '' then
begin
if edt_Get.CanFocus then edt_Get.SetFocus;
ShowMessage('请输入要查询的key');
Abort;
end;
iBegin := GetTickCount;
sValue := FHashList.Values[edt_Get.Text];
//sValue := FHashList.ValueFromIndex[ FHashList.IndexOfName(edt_Get.Text) ];
iEnd := GetTickCount - iBegin;
Memo2.Lines.Add('------------------HashedStringList Get-----------------');
Memo2.Lines.Add(sValue + '--->' + IntToStr(iEnd) + 'ms');
except
end;
end;
end.
来源:https://www.cnblogs.com/markwu/p/13601095.html |