delphi的hashmap

delphi的hashmap

/// 支持D7,更低版本没有测试,支持跨OS

unit hashMap;

interface

uses
  SysUtils;

type
  PHashData = ^THashData;

  THashData = record
    KeyS: string;
    KeyI: Int64;
    Next: PHashData;
    Data: Pointer;
  end;

  THashMap = class
  private
    FBucketsSize: Cardinal;                  // 桶大小
    FBuckets: array of PHashData;    // 桶
  public
    constructor Create(BucketsSize: Cardinal = 20000);
    destructor destroy; override;
  public
    procedure SetValue(const key: string; val: Pointer); overload;
    procedure SetValue(const key: integer; val: Pointer); overload;
    function GetValue(const key: string; var val: Pointer): Boolean; overload;
    function GetValue(const key: Integer; var val: Pointer): Boolean; overload;
  end;

function hashOf(const p: Pointer; l: Integer): Integer; overload;

function hashOf(const s: string): Integer; overload;

implementation

function hashOf(const p: Pointer; l: Integer): Integer; overload;
var
  ps: PInteger;
  lr: Integer;
begin
  Result := 0;
  if l > 0 then
  begin
    ps := p;
    lr := (l and $03);
    l := (l and $FFFFFFFC);
    while l > 0 do
    begin
      Result := ((Result shl 5) or (Result shr 27)) xor ps^;
      Inc(ps);
      Dec(l, 4);
    end;
    if lr <> 0 then
    begin
      l := 0;
      Move(ps^, l, lr);
      Result := ((Result shl 5) or (Result shr 27)) xor l;
    end;
  end;
end;

function hashOf(const s: string): Integer; overload;
begin
  Result := hashOf(PChar(s), Length(s) * SizeOf(Char));
end;

{ THashMap }

constructor THashMap.Create(BucketsSize: Cardinal = 20000);
var
  i: Integer;
begin
  FBucketsSize := BucketsSize;
  SetLength(FBuckets, FBucketsSize);
  for i := 0 to FBucketsSize - 1 do
    FBuckets[i] := nil;
end;

destructor THashMap.destroy;
var
  I: Integer;
  item, lNext: PHashData;
begin
  for I := 0 to High(FBuckets) do
  begin
    lNext := FBuckets[I];
    while lNext <> nil do
    begin
      item := lNext;
      lNext := lNext.Next;
      Dispose(item);
    end;
  end;
  inherited;
end;

function THashMap.GetValue(const key: string; var val: Pointer): Boolean;
var
  Idx: Cardinal;
  Rec: PHashData;
  HashV: Cardinal;
begin
  Result := False;
  HashV := Cardinal(hashOf(key));
  Idx := HashV mod Cardinal(FBucketsSize);
  Rec := FBuckets[Idx];
  while Assigned(Rec) do
  begin
    if Rec.KeyS = key then
    begin
      val := Rec.Data;
      Result := True;
      Break;
    end;
    Rec := Rec.Next;
  end;
end;

procedure THashMap.SetValue(const key: string; val: Pointer);
var
  Idx: Integer;
  Rec, MatchtedRec: PHashData;
  hashVal: Cardinal;
begin
  hashVal := Cardinal(hashof(key));
  Idx := hashVal mod Cardinal(FBucketsSize);
  Rec := FBuckets[Idx];
  MatchtedRec := nil;
  while Assigned(Rec) do
  begin
    if Rec.KeyS = key then
    begin
      MatchtedRec := Rec;
      Break;
    end;
    Rec := Rec.Next;
  end;
  if MatchtedRec <> nil then
  begin
    MatchtedRec.Data := val;
  end
  else
  begin
    New(MatchtedRec);
    MatchtedRec.KeyS := key;
    MatchtedRec.Data := val;
    MatchtedRec.Next := FBuckets[Idx];
    FBuckets[Idx] := MatchtedRec;
  end;
end;

function THashMap.GetValue(const key: Integer; var val: Pointer): Boolean;
var
  Idx: Cardinal;
  Rec: PHashData;
begin
  Result := False;
  Idx := Cardinal(key) mod FBucketsSize;
  Rec := FBuckets[Idx];
  while Assigned(Rec) do
  begin
    if Rec.KeyI = key then
    begin
      val := Rec.Data;
      Result := True;
      Break;
    end;
    Rec := Rec.Next;
  end;
end;

procedure THashMap.SetValue(const key: integer; val: Pointer);
var
  Idx: Integer;
  Rec, MatchtedRec: PHashData;
begin
  Idx := Cardinal(key) mod Cardinal(FBucketsSize);
  Rec := FBuckets[Idx];
  MatchtedRec := nil;
  while Assigned(Rec) do
  begin
    if Rec.KeyI = key then
    begin
      MatchtedRec := Rec;
      Break;
    end;
    Rec := Rec.Next;
  end;
  if MatchtedRec <> nil then
  begin
    MatchtedRec.Data := val;
  end
  else
  begin
    GetMem(MatchtedRec, SizeOf(THashData));
    MatchtedRec.KeyI := key;
    MatchtedRec.Data := val;
    MatchtedRec.Next := FBuckets[Idx];
    FBuckets[Idx] := MatchtedRec;
  end;
end;

end.

  

posted @ 2020-09-10 11:08  delphi中间件  阅读(1064)  评论(0编辑  收藏  举报