曾經看到很多人在嚷嚷Delphi沒有哈希表,這些人的動手意識姑且不論,卻還有很多人以此來證明Delphi比別的語言垃圾,實在是...
好,牢騷打住,轉接正題。
TStringList是我們常用的字符串列表類型,用法就不在這裏贅述,但是,在數據其項數增多時,其搜索(主要是name/key搜索和indexof搜索)性能會急劇下降,原因是TStringList的內部存儲使用了鏈表形式,而搜索操作使用了循環遍歷方式。
值得高興的是,在iniFiles單元,Delphi爲我們提供了THashedStringList類型,即,經過哈希處理的TStringList,它繼承自TStringList,只是對搜索方法進行了優化,因此,我們完全可以放心的在大量字符串搜索的時候使用它來代替TStringList,而需要改變的只是在:=的後面用THashedStringList.create來代替TStringList.create,但其速度卻提高了一個數量級。
爲了顯示兩者間性能的差距,我寫了幾個簡單的語句來測試他們各自的特性。
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, StrUtils,IniFiles;
type
TForm1 = class(TForm)
btn1: TButton;
mmo1: TMemo;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
procedure testTHashStringList;
procedure testTStringList;
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses DateUtils;
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject);
begin
testTStringList;
mmo1.Lines.Add('--------------------');
testTHashStringList;
end;
procedure TForm1.testTHashStringList;
var
hsl: THashedStringList;
I: Integer;
datePointer: TDateTime;
hslTime, hslTimeC, hslTimeI: Int64;
tempInt: Integer;
tempstr: string ;
begin
hslTime := 0;
hslTimeC := 0;
datePointer := Now();
hsl := THashedStringList.Create();
for I := 1 to 200000 do
begin
hsl.Add('string_'+IntToStr(i));
end;
hslTime := MilliSecondsBetween(Now, datePointer);
mmo1.Lines.Add('200000 項 THashedStringList 創建耗時:'+IntToStr(hslTime)+'毫秒');
datePointer := Now();
for I := 0 to 200 do
begin
tempInt := hsl.IndexOf('string_'+IntToStr(i*1000));
end;
hslTime := MilliSecondsBetween(Now, datePointer);
mmo1.Lines.Add('200 項字符串搜索 THashedStringList 耗時:'+IntToStr(hslTime)+'毫秒');
datePointer := Now;
for I := 1 to 200000 do
begin
tempstr := hsl.Strings[i -1];
end;
hslTime := MilliSecondsBetween(Now, datePointer);
mmo1.Lines.Add('200000 項索引搜索 THashedStringList 耗時:'+IntToStr(hslTime)+'毫秒');
hsl.Clear;
datePointer := Now;
for I := 1 to 100000 do
begin
hsl.Insert(i-1, 'string_'+IntToStr(i));
end;
hslTime := MilliSecondsBetween(Now, datePointer);
mmo1.Lines.Add('100000 項 THashedStringList 隨位置插入耗時:'+IntToStr(hslTime)+'毫秒');
datePointer := Now;
for I := 1 to 100000 do
begin
hsl.Insert(0, 'string_'+IntToStr(i));
end;
hslTime := MilliSecondsBetween(Now, datePointer);
mmo1.Lines.Add('100000 項 THashedStringList 0位置插入耗時:'+IntToStr(hslTime)+'毫秒');
end;
procedure TForm1.testTStringList;
var
sl: TStringList;
I: Integer;
datePointer: TDateTime;
slTime, slTimeC, slTimeI: Int64;
tempInt: Integer;
tempstr: string ;
begin
slTime := 0;
slTimeC := 0;
datePointer := Now();
sl := TStringList.Create;
for I := 1 to 200000 do
begin
sl.Add('string_'+IntToStr(i));
end;
slTime := MilliSecondsBetween(Now, datePointer);
mmo1.Lines.Add('200000 項 TStringList 創建耗時:'+IntToStr(slTime)+'毫秒');
datePointer := Now;
for I := 0 to 200 do
begin
tempInt := sl.IndexOf('string_'+IntToStr(i*1000));
end;
slTime := MilliSecondsBetween(Now, datePointer);
mmo1.Lines.Add('200 項字符串搜索 TStringList 耗時:'+IntToStr(slTime)+'毫秒');
datePointer := Now;
for I := 1 to 200000 do
begin
tempstr := sl.Strings[i -1];
end;
slTime := MilliSecondsBetween(Now, datePointer);
mmo1.Lines.Add('200000 項索引搜索 TStringList 耗時:'+IntToStr(slTime)+'毫秒');
datePointer := Now;
for I := 1 to 100000 do
begin
sl.Insert(i-1,'string_'+IntToStr(i));
end;
slTime := MilliSecondsBetween(Now, datePointer);
mmo1.Lines.Add('100000 項 TStringList 隨位置插入耗時:'+IntToStr(slTime)+'毫秒');
datePointer := Now;
for I := 1 to 100000 do
begin
sl.Insert(0,'string_'+IntToStr(i));
end;
slTime := MilliSecondsBetween(Now, datePointer);
mmo1.Lines.Add('100000 項 TStringList 0位置插入耗時:'+IntToStr(slTime)+'毫秒');
end;
end.
編譯運行程序,其運行結果:
200000 項 TStringList 創建耗時:109毫秒
200 項字符串搜索 TStringList 耗時:11514毫秒
200000 項索引搜索 TStringList 耗時:31毫秒
100000 項 TStringList 隨位置插入耗時:85828毫秒
100000 項 TStringList 0位置插入耗時:148734毫秒
--------------------
200000 項 THashedStringList 創建耗時:108毫秒
200 項字符串搜索 THashedStringList 耗時:188毫秒
200000 項索引搜索 THashedStringList 耗時:15毫秒
100000 項 THashedStringList 隨位置插入耗時:63毫秒
100000 項 THashedStringList 0位置插入耗時:55640毫秒
(測試環境:Windows2003 SP1 +Delphi 2006 Update 2 HotFix1-9 +1G內存 +P-D2.8G雙核)
結果很明顯,兩者在創建的時候,性能並沒有差距(之前聽人說THashedStringList在增加和插入操作時會比 TStringList慢,在此並沒有顯示出來,不知道是不是因爲THashedStringList並不是人們說的那樣,在每次插入項時都做哈希操作,還請各位不吝賜教),而200 項字符串搜索(從1到2000000項勻距搜索200項)中,兩者的性能竟差如此懸殊。其後的各項測試也在預料之中。
由此可見,THashedStringList能更好的代替我們常用的TStringList來工作,我們爲什麼要拒絕呢?
另外,iniFiles單元還提供了TStringHash,但只是對key進行了哈希操作,一般不常用。