有許多程式員都喜歡使用TStringList類作為KVStore for Redis,這是不錯的用法。但是TStringList本身只是對資料線性儲存,當資料量大時,對其檢索效率極為低下。Delphi在在IniFiles 單元中定義了另一個TStringList類,採用了雜湊技術儲存資料,它就是THashedStringList類。下面這段代碼就是摘自IniFiles單元中對THashedStringList的定義。
THashedStringList = class(TStringList)
private
FValueHash: TStringHash;
FNameHash: TStringHash;
FValueHashValid: Boolean;
FNameHashValid: Boolean;
procedure UpdateValueHash;
procedure UpdateNameHash;
protected
procedure Changed; override;
public
destructor Destroy; override;
function IndexOf(const S: string): Integer; override;
function IndexOfName(const Name: string): Integer; override;
end;
基本的TStringList類是使用數組以線性方式儲存所有子項的,所以無論使用其IndexOf方法還是IndexOfName方法都是使用線性尋找法,這種查尋方法的時間複雜度在最好情況為T(1),即第一個子項即為查詢項,最壞情況為T(N),N為子項個數,即尋找項為最後一項。所以,當資料量比較大時其查詢是毫無效率可言的。
THashedStringList類中添加了兩個TStringHash私人成員,分別用來存放對其子項鍵名雜湊表和索引值雜湊表。當調用其IndexOf方法或是IndexOfName方法時,此類會首先檢查是否已經為索引值或是鍵名建立雜湊表,如果沒有,則建立之,否則直接使用雜湊演算法時行尋找。
function THashedStringList.IndexOf(const S: string): Integer;
begin
UpdateValueHash; //建立索引值雜湊表
if not CaseSensitive then
Result := FValueHash.ValueOf(AnsiUpperCase(S))
else
Result := FValueHash.ValueOf(S);
end;
function THashedStringList.IndexOfName(const Name: string): Integer;
begin
UpdateNameHash; //建立健名雜湊表
if not CaseSensitive then
Result := FNameHash.ValueOf(AnsiUpperCase(Name))
else
Result := FNameHash.ValueOf(Name);
end;
學過資料結構的朋友都知道,當資料量不是很大時,如幾百、幾千時雜湊演算法的優勢並不是很明顯,和普通的線性尋找效能差不了多少,但是隨著資料量在增大,其效能的提升是相當可觀的。所以建議各位程式員朋友,如果需要使用TStringList儲存大資料量時,請使用THashedStringList代替。