Delphi中的THashTable

在Delphi中,Inifiles单元中有一个TStringHash的类,不过它的Value仅支持Integer(其实也不是问题,有其它类型可以将变量变为Pointer),有点不舒服,今天没事做就把它替换为variant了,其中Key的名称大小写无关,就是为了加快开发速度!

使用Hashtable,查找和删除复杂度都是常数级别的!

type

  PPHashItem = ^PHashItem;

  PHashItem = ^THashItem;

  THashItem = record

    Next: PHashItem;

    Key: String;

    Value: Variant;

  end;

  THashTable = class

  private

    Buckets: array of PHashItem;

  protected

    function Find(const Key: String): PPHashItem;

    function HashOf(const Key: String): Cardinal; virtual;

  public

    constructor Create(Size: Cardinal = 256);

    destructor Destroy; override;

    procedure Put(const Key: String; Value: Variant);

    procedure Clear;

    procedure Remove(const Key: String);

    function Modify(const Key: String; Value: Variant): Boolean;

    function Get(const Key: String): Variant;

    function ContainKey(const Key: String):boolean;

  end;

procedure THashTable.Clear;

var

  I: Integer;

  P, N: PHashItem;

begin

  for I := 0 to Length(Buckets) - 1 do

  begin

    P := Buckets[I];

    while P <> nil do

    begin

      N := P^.Next;

      Dispose(P);

      P := N;

    end;

    Buckets[I] := nil;

  end;

end;

function THashTable.ContainKey(const Key: String): boolean;

var

  P: PHashItem;

begin

  P := Find(Key)^;

  if P <> nil then

  begin

    Result := True;

  end

  else

    Result := False;

end;

constructor THashTable.Create(Size: Cardinal);

begin

  inherited Create;

  SetLength(Buckets, Size);

end;

destructor THashTable.Destroy;

begin

  Clear;

  inherited Destroy;

end;

function THashTable.Find(const Key: String): PPHashItem;

var

  Hash: Integer;

begin

  Hash := HashOf(Key) mod Cardinal(Length(Buckets));

  Result := @Buckets[Hash];

  while Result^ <> nil do

  begin

    if Result^.Key = Key then

      Exit

    else

      Result := @Result^.Next;

  end;

end;

function THashTable.Get(const Key: String): Variant;

var

  P: PHashItem;

begin

  P := Find(AnsiUpperCase(Key))^;

  if P <> nil then

    Result := P^.Value

  else

    Result := -1;

end;

function THashTable.HashOf(const Key: String): Cardinal;

var

  I: Integer;

begin

  Result := 0;

  for I := 1 to Length(Key) do

    Result := ((Result shl 2) or (Result shr (SizeOf(Result) * 8 - 2))) xor

      Ord(Key[I]);

end;

function THashTable.Modify(const Key: String; Value: Variant): Boolean;

var

  P: PHashItem;

begin

  P := Find(Key)^;

  if P <> nil then

  begin

    Result := True;

    P^.Value := Value;

  end

  else

    Result := False;

end;

procedure THashTable.Put(const Key: String; Value: Variant);

var

  Hash: Integer;

  Bucket: PHashItem;

begin

  Hash := HashOf(AnsiUpperCase(Key)) mod Cardinal(Length(Buckets));

  New(Bucket);

  Bucket^.Key := AnsiUpperCase(Key);

  Bucket^.Value := Value;

  Bucket^.Next := Buckets[Hash];

  Buckets[Hash] := Bucket;

end;

procedure THashTable.Remove(const Key: String);

var

  P: PHashItem;

  Prev: PPHashItem;

begin

  Prev := Find(Key);

  P := Prev^;

  if P <> nil then

  begin

    Prev^ := P^.Next;

    Dispose(P);

  end;

end;
View Code
使用

























var

  Demo:THashTable;

begin

  Demo:=THashTable.Create();

  try

    Demo.Put('id',1);

    ShowMessage(Demo.Get('id'));

  finally

    Demo.Free;

  end;

end;
View Code

 

你可能感兴趣的:(Hashtable)