修正 THashedStringList 在插入和 PutObject 时的速度缺陷

建议用 TFastHashedStringListMini ,更安全(版本安全),不过TFastHashedStringList 更清晰完整.

--------------------------------------------------

unit uFastHashedStringList;

//修正 THashedStringList 在插入和 PutObject 时的速度缺陷
//THashedStringList 主要的问题是重写了   ,而插入和 PutObject 等修改内容的操作都会触发这个事件,
//而这个事件是要表明更新索引的,所以第次都更新索引引起了性能的急剧下降

interface
uses
  IniFiles,SysUtils, Classes;

type
  TFastHashedStringListMini = class(THashedStringList)
  private
    FChangeTag:Boolean;
  protected
    procedure Changed; override;

  public
    //在为屏蔽了 Changed ,所以在需要更新索引时一定要调用这个函数
    //procedure SetChangeTag();
    //更新索引
    procedure UpdateIndex();

  end;


//直接来自 TFastHashedString
type
  TFastHashedStringList = class(TStringList)
  private
    FValueHash: TStringHash;
    FNameHash: TStringHash;
    FValueHashValid: Boolean;
    FNameHashValid: Boolean;
    procedure UpdateValueHash;
    procedure UpdateNameHash;
  protected
    //procedure Changed; override;
  public
    FList: PStringItemList;
    destructor Destroy; override;
    function IndexOf(const S: string): Integer; override;
    function IndexOfName(const Name: string): Integer; override;
    procedure PutObject2(Index: Integer; AObject: TObject);//test
    //在为屏蔽了 Changed ,所以在需要更新索引时一定要调用这个函数
    procedure SetChangeTag();
    //更新索引
    procedure UpdateIndex();
  end;

implementation

{ TFastHashedStringList }

//procedure TFastHashedStringList.Changed;
//begin
//  //inherited;
//  //恢复为 procedure TStringList.Changed; 的内容
//
//  //if (FUpdateCount = 0) and Assigned(FOnChange) then
//  //  FOnChange(Self);
//
//  Self.FValueHashValid := True;
//end;

{ THashedStringList }

//procedure THashedStringList.Changed;
//begin
//  inherited Changed;
//  FValueHashValid := False;
//  FNameHashValid := False;
//end;

destructor TFastHashedStringList.Destroy;
begin
  FValueHash.Free;
  FNameHash.Free;
  inherited Destroy;
end;

function TFastHashedStringList.IndexOf(const S: string): Integer;
begin
  UpdateValueHash;
  if not CaseSensitive then
    Result :=  FValueHash.ValueOf(AnsiUpperCase(S))
  else
    Result :=  FValueHash.ValueOf(S);
end;

function TFastHashedStringList.IndexOfName(const Name: string): Integer;
begin
  UpdateNameHash;
  if not CaseSensitive then
    Result := FNameHash.ValueOf(AnsiUpperCase(Name))
  else
    Result := FNameHash.ValueOf(Name);
end;

//--------------------------------------------------
procedure TFastHashedStringList.PutObject2(Index: Integer; AObject: TObject);
begin
//  if (Index < 0) or (Index >= FCount) then Error(@SListIndexError, Index);
//  Changing;
  if FList= nil then
  ReallocMem(FList, 20000 * 2000 * SizeOf(TStringItem));

  FList^[Index].FObject := AObject;
  Changed;//是这一个造成特别的慢//clq
end;
//--------------------------------------------------

procedure TFastHashedStringList.SetChangeTag;
begin
  FValueHashValid := False;
  FNameHashValid := False;
end;

procedure TFastHashedStringList.UpdateIndex;
begin
  SetChangeTag();
  UpdateValueHash;
  UpdateNameHash;
 
end;

procedure TFastHashedStringList.UpdateNameHash;
var
  I: Integer;
  P: Integer;
  Key: string;
begin
  if FNameHashValid then Exit;
 
  if FNameHash = nil then
    FNameHash := TStringHash.Create
  else
    FNameHash.Clear;
  for I := 0 to Count - 1 do
  begin
    Key := Get(I);
    P := AnsiPos('=', Key);
    if P <> 0 then
    begin
      if not CaseSensitive then
        Key := AnsiUpperCase(Copy(Key, 1, P - 1))
      else
        Key := Copy(Key, 1, P - 1);
      FNameHash.Add(Key, I);
    end;
  end;
  FNameHashValid := True;
end;

procedure TFastHashedStringList.UpdateValueHash;
var
  I: Integer;
begin
  if FValueHashValid then Exit;
 
  if FValueHash = nil then
    FValueHash := TStringHash.Create
  else
    FValueHash.Clear;
  for I := 0 to Count - 1 do
    if not CaseSensitive then
      FValueHash.Add(AnsiUpperCase(Self[I]), I)
    else
      FValueHash.Add(Self[I], I);
  FValueHashValid := True;
end;


{ TFastHashedStringListTmp }

procedure TFastHashedStringListMini.Changed;
begin
  //inherited;
  //恢复为 procedure TStringList.Changed; 的内容

  //if (FUpdateCount = 0) and Assigned(FOnChange) then
  //  FOnChange(Self);

  //这样修改不太安全,不过比全部重写要好
  if (UpdateCount = 0) and Assigned(OnChange) then
    OnChange(Self);

  //--------------------------------------------------
  if FChangeTag then inherited;
  FChangeTag := False;

end;

procedure TFastHashedStringListMini.UpdateIndex;
begin
  FChangeTag := True;
  Changed;
end;

end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值