晚
晚起的小虫
Unregistered / Unconfirmed
GUEST, unregistred user!
小弟因实现须要,便自己写一个Hash表的实现,以提供多线程下的高效Hash添加查找。
初步已实现完成,因我要考虑把它写成为了一比较通用的Hash表,所以用了不少接口。
但是我觉得我这个模型调用起来好像有点麻烦。不知道各位高人对此有何建议。测试工程下载地址:http://sorong.vicp.net/hash.rar
{
Hash 表及相关定义和实现
晚起的小虫
2006-6-11
THashTable 为Hash表
TCalHashCode 为计算Hash值的函数。外部传入到THashTable
THashItemQueue 为解决Hash值冲突的链表
ICompare 比较的接口,在Hash表中查找Key时用,节点对象必须实现该接口。
TItemObject 节点虚类。
}
unit uHash;
interface
uses
Classes, SysUtils, Forms, SyncObjs;
type
//----------------节点----------------------
//--比较的接口
ICompare = interface
['{C43DAF4B-E08D-4E09-B830-342D1B10B7B7}'] //一定要GUID,以做接口转换
// a>b 返回 1,相等=0, a<b返回-1
//为了适应数值类型和对象引用,故采用指针方式传参
function CompareToKey(Key: Pointer): Integer;
end;
//--节点纯虚类
TItemObject = class(TInterfacedObject, ICompare)
public
function CompareToKey(Key: Pointer): Integer
virtual
abstract;
end;
//---------------节点链表----------------------------
//--Hash节点链表,解决Hash冲突。
{
THashItemQueue以保存接口的方式保存对象引用,要保存的节点对象必须实现IInterface和ICompare接口
}
THashItemQueue = class
protected
FLock: TCriticalSection;
FList: TInterfaceList;
function GetItems(i: Integer): IInterface;
function GetCount: Integer;
public
constructor Create;
destructor Destroy
override;
property Items[i: Integer]: IInterface read GetItems;
//按Key查找,找到返回节点的位置,找不到返回-1
function indexOf(Key: Pointer): Integer;
//按Key查找,找到返回节点接口,找不到返回nil
function Find(Key: Pointer): IInterface;
property Count: Integer read GetCount;
//添加节点,重复的忽略
procedure Add(Key: Pointer
Item: IInterface);
procedure Delete(i: Integer);
procedure Lock
//进入临界区锁定
procedure UnLock
//解除临界区锁定
end;
//----------------HashTable---------------------------
//--利用接口的引用计数来统计当前正在被Lock中的THashItemQueue个数统计
TLockStater = class(TInterfacedObject)
protected
function GetLockCount: Integer;
public
property LockCount: Integer read GetLockCount;
end;
//--计算Hash的函数
TCalHashCode = function(Key: Pointer): Integer of object;
//--Hash接口
IHashTable = interface
['{A05C330A-DA86-4909-BBF5-B98931293735}']
function Find(Key: Pointer): IInterface;
procedure Add(Key: Pointer
obj: IInterface);
procedure Delete(Key: Pointer);
end;
//--Hash链表
THashTable = class(TInterfacedObject, IHashTable)
private
function GetUseItemCount: Integer;
protected
FLockStaterObj: TLockStater;
FLockStater: IInterface
//Lock计数自引用接口
FCount: Integer;
FCalHashCode: TCalHashCode;
FList: TList;
function FindItem(Key: Pointer): THashItemQueue;
public
constructor Create(ItemsCount: Integer
CalHashCode: TCalHashCode);
destructor Destroy
override;
//查找,找到返回对象接口,找不到返回nil
function Find(Key: Pointer): IInterface;
//添加接口,如果Key已存在,则不添加
procedure Add(Key: Pointer
obj: IInterface);
//删除一个Key
procedure Delete(Key: Pointer);
property Count: Integer read FCount;
property UseItemCount: Integer read GetUseItemCount;
end;
//----------------------------------------------
implementation
{ TLockStater }
function TLockStater.GetLockCount: Integer;
begin
Result := FRefCount;
end;
{ THashItemQueue }
procedure THashItemQueue.Add(Key: Pointer
Item: IInterface);
begin
if indexOf(Key) >= 0 then
Exit
//如果原先存在就退出
FList.Add(Item);
end;
constructor THashItemQueue.Create;
begin
inherited;
FList := TInterfaceList.Create;
FLock := TCriticalSection.Create;
end;
procedure THashItemQueue.Delete(i: Integer);
begin
FList.Delete(i);
end;
destructor THashItemQueue.Destroy;
var
i: Integer;
begin
for i := FList.Count - 1 downto 0 do
begin
FList.Delete(i);
end;
FLock.Free;
FList.Free;
inherited;
end;
function THashItemQueue.Find(Key: Pointer): IInterface;
var
i: Integer;
begin
i := indexOf(Key);
if i >= 0 then Result := FList.Items
else Result := nil;
end;
function THashItemQueue.GetCount: Integer;
begin
Result := FList.Count;
end;
function THashItemQueue.GetItems(i: Integer): IInterface;
begin
Result := FList.Items;
end;
function THashItemQueue.indexOf(Key: Pointer): Integer;
var
i: Integer;
// Comparer:ICompare;
begin
Result := -1;
if FList.Count = 0 then exit;
for i := 0 to FList.Count - 1 do
begin
if (FList.Items as ICompare).CompareToKey(Key) = 0 then
begin
Result := i;
Break;
end;
end;
end;
procedure THashItemQueue.Lock;
begin
FLock.Enter;
end;
procedure THashItemQueue.UnLock;
begin
FLock.Leave;
end;
{ THashTable }
procedure THashTable.Add(Key: Pointer
obj: IInterface);
var
Item: THashItemQueue;
tmp: IInterface;
begin
tmp := FLockStater;
Item := FindItem(Key);
Item.Lock;
try
Item.Add(Key, obj);
finally
Item.UnLock;
end;
end;
constructor THashTable.Create(ItemsCount: Integer
CalHashCode: TCalHashCode);
var
i: Integer;
begin
inherited Create;
FCount := ItemsCount;
FCalHashCode := CalHashCode;
FList := TList.Create;
for i := 0 to FCount - 1 do
begin
FList.Add(THashItemQueue.Create);
end;
FLockStaterObj := TLockStater.Create;
FLockStater := FLockStaterObj;
end;
procedure THashTable.Delete(Key: Pointer);
var
Item: THashItemQueue;
i: Integer;
tmp: IInterface;
begin
tmp := FLockStater;
Item := FindItem(Key);
Item.Lock;
try
i := Item.indexOf(Key);
if i >= 0 then
Item.Delete(i);
finally
Item.UnLock;
end;
end;
destructor THashTable.Destroy;
var
i: Integer;
begin
for i := FCount - 1 downto 0 do
TObject(FList.Items).Free;
FList.Free;
FLockStater := nil;
inherited;
end;
function THashTable.Find(Key: Pointer): IInterface;
var
Item: THashItemQueue;
i: Integer;
tmp: IInterface;
begin
tmp := FLockStater;
Item := FindItem(Key);
Item.Lock;
try
Result := Item.Find(Key);
finally
Item.UnLock;
end;
end;
function THashTable.FindItem(Key: Pointer): THashItemQueue;
var
i: integer;
begin
i := FCalHashCode(Key);
Result := THashItemQueue(FList.Items);
end;
function THashTable.GetUseItemCount: Integer;
begin
Result := FLockStaterObj.LockCount;
end;
end.
初步已实现完成,因我要考虑把它写成为了一比较通用的Hash表,所以用了不少接口。
但是我觉得我这个模型调用起来好像有点麻烦。不知道各位高人对此有何建议。测试工程下载地址:http://sorong.vicp.net/hash.rar
{
Hash 表及相关定义和实现
晚起的小虫
2006-6-11
THashTable 为Hash表
TCalHashCode 为计算Hash值的函数。外部传入到THashTable
THashItemQueue 为解决Hash值冲突的链表
ICompare 比较的接口,在Hash表中查找Key时用,节点对象必须实现该接口。
TItemObject 节点虚类。
}
unit uHash;
interface
uses
Classes, SysUtils, Forms, SyncObjs;
type
//----------------节点----------------------
//--比较的接口
ICompare = interface
['{C43DAF4B-E08D-4E09-B830-342D1B10B7B7}'] //一定要GUID,以做接口转换
// a>b 返回 1,相等=0, a<b返回-1
//为了适应数值类型和对象引用,故采用指针方式传参
function CompareToKey(Key: Pointer): Integer;
end;
//--节点纯虚类
TItemObject = class(TInterfacedObject, ICompare)
public
function CompareToKey(Key: Pointer): Integer
virtual
abstract;
end;
//---------------节点链表----------------------------
//--Hash节点链表,解决Hash冲突。
{
THashItemQueue以保存接口的方式保存对象引用,要保存的节点对象必须实现IInterface和ICompare接口
}
THashItemQueue = class
protected
FLock: TCriticalSection;
FList: TInterfaceList;
function GetItems(i: Integer): IInterface;
function GetCount: Integer;
public
constructor Create;
destructor Destroy
override;
property Items[i: Integer]: IInterface read GetItems;
//按Key查找,找到返回节点的位置,找不到返回-1
function indexOf(Key: Pointer): Integer;
//按Key查找,找到返回节点接口,找不到返回nil
function Find(Key: Pointer): IInterface;
property Count: Integer read GetCount;
//添加节点,重复的忽略
procedure Add(Key: Pointer
Item: IInterface);
procedure Delete(i: Integer);
procedure Lock
//进入临界区锁定
procedure UnLock
//解除临界区锁定
end;
//----------------HashTable---------------------------
//--利用接口的引用计数来统计当前正在被Lock中的THashItemQueue个数统计
TLockStater = class(TInterfacedObject)
protected
function GetLockCount: Integer;
public
property LockCount: Integer read GetLockCount;
end;
//--计算Hash的函数
TCalHashCode = function(Key: Pointer): Integer of object;
//--Hash接口
IHashTable = interface
['{A05C330A-DA86-4909-BBF5-B98931293735}']
function Find(Key: Pointer): IInterface;
procedure Add(Key: Pointer
obj: IInterface);
procedure Delete(Key: Pointer);
end;
//--Hash链表
THashTable = class(TInterfacedObject, IHashTable)
private
function GetUseItemCount: Integer;
protected
FLockStaterObj: TLockStater;
FLockStater: IInterface
//Lock计数自引用接口
FCount: Integer;
FCalHashCode: TCalHashCode;
FList: TList;
function FindItem(Key: Pointer): THashItemQueue;
public
constructor Create(ItemsCount: Integer
CalHashCode: TCalHashCode);
destructor Destroy
override;
//查找,找到返回对象接口,找不到返回nil
function Find(Key: Pointer): IInterface;
//添加接口,如果Key已存在,则不添加
procedure Add(Key: Pointer
obj: IInterface);
//删除一个Key
procedure Delete(Key: Pointer);
property Count: Integer read FCount;
property UseItemCount: Integer read GetUseItemCount;
end;
//----------------------------------------------
implementation
{ TLockStater }
function TLockStater.GetLockCount: Integer;
begin
Result := FRefCount;
end;
{ THashItemQueue }
procedure THashItemQueue.Add(Key: Pointer
Item: IInterface);
begin
if indexOf(Key) >= 0 then
Exit
//如果原先存在就退出
FList.Add(Item);
end;
constructor THashItemQueue.Create;
begin
inherited;
FList := TInterfaceList.Create;
FLock := TCriticalSection.Create;
end;
procedure THashItemQueue.Delete(i: Integer);
begin
FList.Delete(i);
end;
destructor THashItemQueue.Destroy;
var
i: Integer;
begin
for i := FList.Count - 1 downto 0 do
begin
FList.Delete(i);
end;
FLock.Free;
FList.Free;
inherited;
end;
function THashItemQueue.Find(Key: Pointer): IInterface;
var
i: Integer;
begin
i := indexOf(Key);
if i >= 0 then Result := FList.Items
else Result := nil;
end;
function THashItemQueue.GetCount: Integer;
begin
Result := FList.Count;
end;
function THashItemQueue.GetItems(i: Integer): IInterface;
begin
Result := FList.Items;
end;
function THashItemQueue.indexOf(Key: Pointer): Integer;
var
i: Integer;
// Comparer:ICompare;
begin
Result := -1;
if FList.Count = 0 then exit;
for i := 0 to FList.Count - 1 do
begin
if (FList.Items as ICompare).CompareToKey(Key) = 0 then
begin
Result := i;
Break;
end;
end;
end;
procedure THashItemQueue.Lock;
begin
FLock.Enter;
end;
procedure THashItemQueue.UnLock;
begin
FLock.Leave;
end;
{ THashTable }
procedure THashTable.Add(Key: Pointer
obj: IInterface);
var
Item: THashItemQueue;
tmp: IInterface;
begin
tmp := FLockStater;
Item := FindItem(Key);
Item.Lock;
try
Item.Add(Key, obj);
finally
Item.UnLock;
end;
end;
constructor THashTable.Create(ItemsCount: Integer
CalHashCode: TCalHashCode);
var
i: Integer;
begin
inherited Create;
FCount := ItemsCount;
FCalHashCode := CalHashCode;
FList := TList.Create;
for i := 0 to FCount - 1 do
begin
FList.Add(THashItemQueue.Create);
end;
FLockStaterObj := TLockStater.Create;
FLockStater := FLockStaterObj;
end;
procedure THashTable.Delete(Key: Pointer);
var
Item: THashItemQueue;
i: Integer;
tmp: IInterface;
begin
tmp := FLockStater;
Item := FindItem(Key);
Item.Lock;
try
i := Item.indexOf(Key);
if i >= 0 then
Item.Delete(i);
finally
Item.UnLock;
end;
end;
destructor THashTable.Destroy;
var
i: Integer;
begin
for i := FCount - 1 downto 0 do
TObject(FList.Items).Free;
FList.Free;
FLockStater := nil;
inherited;
end;
function THashTable.Find(Key: Pointer): IInterface;
var
Item: THashItemQueue;
i: Integer;
tmp: IInterface;
begin
tmp := FLockStater;
Item := FindItem(Key);
Item.Lock;
try
Result := Item.Find(Key);
finally
Item.UnLock;
end;
end;
function THashTable.FindItem(Key: Pointer): THashItemQueue;
var
i: integer;
begin
i := FCalHashCode(Key);
Result := THashItemQueue(FList.Items);
end;
function THashTable.GetUseItemCount: Integer;
begin
Result := FLockStaterObj.LockCount;
end;
end.