Skip to content
This repository was archived by the owner on Feb 24, 2025. It is now read-only.

TMultiHash

Ivan Semenkov edited this page Oct 16, 2021 · 1 revision

Table of contents

About

A multi hash table stores a set of values which can be addressed by a key. Given the key, the corresponding values can be looked up quickly.

uses
  container.hashtable, container.multihash, utils.functor;
  
type
  generic TMultiHash<K, V, KeyBinaryCompareFunctor, ValueBinaryCompareFunctor> = class

KeyBinaryCompareFunctor and ValueBinaryCompareFunctor is based on utils.functor.TBinaryFunctor interface and used to compare two keys.

TMultiValue

MultiValue uses as internal values list.

type
  TMultiValue = {$IFDEF FPC}specialize{$ENDIF} TList<T, ValueBinaryCompareFunctor>;

TOptionalMultiValue

If macro {$USE_OPTIONAL} is defined, then all methods return a TOptionalMultiValue wrapper, otherwise V.

uses
  utils.optional;

type
  TOptionalMultiValue = {$IFDEF FPC}specialize{$ENDIF} TOptional<TMultiValue>;

For non-existent values, returns a empty TOptionalValue if defined or an EKeyNotExistsException is thrown.

type
  {$IFNDEF USE_OPTIONAL}
  EKeyNotExistsException = class(Exception);
  {$ENDIF}

Create

A new multi hash table can be created by call its constructor.

constructor Create (HashFunc : THashTableHashFunc);

HashTableFunc is a function that generate a hash key for a THashTable value.

Hash functions

Unit container.hashtable contains next hash functions:

function HashPointer(location : Pointer) : Cardinal;

Generate a hash key for a pointer. The value pointed at by the pointer is not used, only the pointer itself.

function HashInteger(location : Integer) : Cardinal;

Generate a hash key for an integer. The value is used to generate the key.

function HashString(location : String) : Cardinal;

Generate a hash key from a string. This is the djb2 string hash function.

function HashStringNoCase(location : String) : Cardinal;

Generate a hash key from a string, ignoring the case of letters. This is the djb2 string hash function.

Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  
  FreeAndNil(hash);
end;

Insert

Insert a value into a multi hash table.

function Insert (Key : K; Value : V) : Boolean;
Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  hash.Insert(1, 'one');
  hash.Insert(1, 'two');
  
  FreeAndNil(hash);
end;

Remove

Remove a value from a multi hash table. Return false if no node with the specified key was found in the tree, true if a node with the specified key was removed.

function Remove (Key : K) : Boolean;
Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  hash.Remove(1);
  
  FreeAndNil(hash);
end;

Search

Search

Look up a value in a multi hash table by key.

function Search (Key : K) : {$IFNDEF USE_OPTIONAL}TMultiValue{$ELSE}TOptionalMultiValue{$ENDIF};

If value not exists returns empty TOptionalMultiValue or raise EKeyNotExistsException.

Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  hash.Search(1);
  
  FreeAndNil(hash);
end;

SearchDefault

Look up a value in a multi hash table by key. Return default value if Key not exists.

function SearchDefault (Key : K; ADefault : V) : TMultiValue;
Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  hash.SearchDefault(1, 'none');
  
  FreeAndNil(hash);
end;

NumEntries

Retrieve the number of entries in a multi hash table.

function NumEntries : Cardinal;
Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  writeln(hash.NumEntries);
  
  FreeAndNil(hash);
end;

IsEmpty

Return true if container is empty.

function IsEmpty : Boolean;
Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  if hash.IsEmpty then
    ;
  
  FreeAndNil(hash);
end;

Iterate

It is possible to iterate for TMultiHash values using in operator. Each value would present as TMultiHash.TIterator object.

uses
  container.hashtable, container.multihash, utils.functor;
  
type
  generic TMultiHash<K, V, KeyBinaryCompareFunctor, ValueBinaryCompareFunctor> = class
  type
  	TIterator = class({$IFDEF FPC}specialize{$ENDIF}
        TForwardIterator<TKeyMultiValuePair, TIterator>)
  end;

TForwardIterator is a abstract class which provide interface for iterable object that can moves to forward side.

Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  iterator : TIntStrMultiHash.TIterator;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  for iterator in hash do
    ;
  
  FreeAndNil(hash);
end;

FirstEntry

Retrive the iterator for first entry in a TMultiHash table.

function FirstEntry : TIterator
Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  iterator : TIntStrMultiHash.TIterator;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  iterator := hash.FirstEntry;
  
  FreeAndNil(hash);
end;

TIterator

HasValue

Return true if iterator has correct value.

function HasValue : Boolean;
Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  iterator : TIntStrMultiHash.TIterator;
  
begin
  hash := TIntStrHashTable.Create(@HashInteger);
  iterator := hash.FirstEntry;
  while iterator.HasValue do
    ;
  
  FreeAndNil(hash);
end;
Next

Retrieve the iterator for next entry in an multi hash table.

function Next : TIterator;
Example
uses
  container.hashtable, contaqiner.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  iterator : TIntStrMultiHash.TIterator;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  iterator := hash.FirstEntry;
  while iterator.HasValue do
  begin
  
    iterator := iterator.Next;
  end;
  
  FreeAndNil(hash);
end;
Key

Return key value.

property Key : K;
Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  iterator : TIntStrMultiHash.TIterator;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  iterator := hash.FirstEntry;
  while iterator.HasValue do
  begin
  	writeln(iterator.Key);
    iterator := iterator.Next;
  end;
  
  FreeAndNil(hash);
end;
Value

Return value.

property Value : TMultiValue;
Example
uses
  container.hashtable, container.multihash, utils.functor;
  
type
  TIntStrMultiHash = {$IFDEF FPC}type specialize{$ENDIF} TMultiHash<Integer, String, TCompareFunctorInteger, TCompareFunctorString>;

var
  hash : TIntStrMultiHash;
  iterator : TIntStrMultiHash.TIterator;
  
begin
  hash := TIntStrMultiHash.Create(@HashInteger);
  iterator := hash.FirstEntry;
  while iterator.HasValue do
  begin
  	writeln(iterator.Value.NthEntry(0).Value);
    iterator := iterator.Next;
  end;
  
  FreeAndNil(hash);
end;