题
是否有鲍勃詹金斯散列函数的情况下不敏感的变体?
Generics.Defaults.BobJenkinsHash
提供了一种快速散列函数。不幸的是它不能在组合使用等的情况下不敏感的比较功能,以便
TCustomStringComparer = class (TEqualityComparer <String>)
function Equals(const Left, Right: String): Boolean; override;
function GetHashCode(const Value: String): Integer; override;
end;
function TCustomStringComparer.Equals (const Left, Right : String) : Boolean;
begin
Result := CompareText (Left, Right) = 0;
end;
function TCustomStringComparer.GetHashCode (const Value : String) : Integer;
begin
Result := Generics.Defaults.BobJenkinsHash (Value [1], Length (Value) * SizeOf (Char), 0);
end;
这是因为TDictionary平等检查时首先比较哈希码,然后使用所提供的比较器。
当然,我可以在我的GetHashCode
功能使用大写,但我不知道它是否会更快,如果我能以某种方式修改散列函数本身。
解决方案
没有,有哈希函数的任何情况下不变的版本。小写或大写它们传递给散列函数之前所有字符串。
其他提示
这将是稍快,但它伤害你的可维护性很多。很少有一个很好的理由,这种类型的微型优化。只要将您的字符串到大写或小写散列像你这样的建议了。
“我们应该忘记小 效率,说的大约97% 时间:过早的优化是 万恶之源。然而,我们不应该 通过我们的机会在 关键的3%。一个好的程序员会 不受这种被哄骗自满 推理,他将是明智的,看看 仔细关键代码;但 只有经过代码已经 确定了” - 高德纳
IMO的整个问题是错误的。引述上散列函数维基百科文章:
一个的散列函数强>是大量的数据,可能是可变大小的量转换成一个小基准,通常是单个整数,可以用作索引,以任何明确定义的过程或数学函数的阵列。
请注意在“数据量” - 没有指定的类型,并且实际上鲍勃詹金斯散列函数具有一个无类型参数const Data
指向待哈希数据。由于输入数据不一定是一个字符序列也没有办法来计算“不区分大小写”散列值。而且,即使它是一个字符序列 - 的大写或lowercasing将取决于字符集和编码。所以,你会需要有ASCII字符串,UTF-8编码字符串,UTF-16 LE编码字符串不同的散列函数,......(你的想法)。
我还需要这样的功能中的一个项目。鲍勃詹的一个在一次一个散列:
function hash(const s: string): cardinal;
var
p, last: PByte;
begin
if s = '' then exit(1);
p := pbyte(pointer(s));
last := p + length(s);
result := 0;
while p < last do begin
if {$ifdef asciionly}p^ < 128{$else}true{$endif} then begin
result := result + p^;
if (p^ >= ord('a')) and (p^ <= ord('z')) then result := result - ord('a') + ord('A');
result := result + (result shl 10);
result := result xor (result shr 6);
end;
inc(p);
end;
result := result + (result shl 3);
result := result xor (result shr 11);
result := result + (result shl 15);
end;
如果asciionly被设置,它也应该给予对于UTF-8和latin1的字符串相同的哈希。
不要忘记停止溢出检查。