Performance 基元键的最快哈希函数/查找

Performance 基元键的最快哈希函数/查找,performance,hash,hashmap,hashtable,Performance,Hash,Hashmap,Hashtable,我的应用程序可能每秒需要在数据集中执行数百万次查找。高性能混凝土相关 这是一个非常具体的用例,其中以下是正确的: 数据集有一组固定的条目。它从不收缩,也不生长。 该键是一个2字节整数的基元 从来没有任何重复的钥匙! 数据集中的条目从不超过200-300个。 键将趋向于在0到1000范围内聚集,而不是均匀分布在-32768到32767之间。 在这种情况下,最快的哈希函数是什么 我至少知道一个: hashValue = key % DATASET_FIXED_SIZE; // Java synta

我的应用程序可能每秒需要在数据集中执行数百万次查找。高性能混凝土相关

这是一个非常具体的用例,其中以下是正确的:

数据集有一组固定的条目。它从不收缩,也不生长。 该键是一个2字节整数的基元 从来没有任何重复的钥匙! 数据集中的条目从不超过200-300个。 键将趋向于在0到1000范围内聚集,而不是均匀分布在-32768到32767之间。 在这种情况下,最快的哈希函数是什么

我至少知道一个:

hashValue = key % DATASET_FIXED_SIZE;  // Java syntax for modulo
但我相信在我的例子中,这个函数的分布是次优的

那么,有了上述知识,最快的哈希函数是什么呢。我是一个数学新手,所以我不知道是否有针对特定用例的。如果有,请告诉我-

注意:由于数据集的大小是固定的,所以我只关心查找性能

编辑:我不太在乎设置时间。我非常愿意用设置时间换取额外的查找性能。这意味着哈希表方法甚至可能不是最好的方法,例如,如果n小于10,则使用蛮力数组扫描,如果1050,则使用一些哈希表方法。n是对的数量,0和50只是我为了说明这一点而提出的一些数字


进一步信息:用例用于内存中的数据结构。

如果您打算使用Java HashMap,我能想到的最好的hashCode实现如下:

public class Sample
{
    private static int CLASS_ID = 0; 
    private final int id;

    public Sample()
    {
        CLASS_ID++;
        id = CLASS_ID;
    }

    // other constructors following the same pattern as in the default constructor

    @Override
    public int hashCode()
    {
        return id;
    }

}
sample的所有构造函数将确保CLASS_ID递增,然后分配给ID字段。此hashCode函数将始终为每个实例返回一个唯一的值,这可以避免将两个实例放在哈希映射中的一个bucket中—假设哈希映射有足够的bucket。这会提高性能,但会以内存为代价

此外,这种实现有两个缺点:

1:如果创建的实例数量超过一个整数所能容纳的大小,则此实现将不起作用。但是,如果您只打算使用200到300个实例,则不应出现这种情况

2:“最大的”缺点是使用CLASS_ID作为全局状态静态变量。在程序的整个运行期间,静态变量将保留在内存中


显然,作为程序员,您的职责是打赌某个实现的成本和权衡。

Koloboke不使用杂音;即使对于线性散列,它也使用了更简单的混合:

在您的情况下,我建议为0-1000范围内的键创建一个直接查找表而不是散列,并使用线性散列表乘以一个随机常数散列其余值。您可以针对每个特定情况尝试几次,看看哪些结果会减少冲突,或者只使用-1640531527这样的值


我明白你的意思,但在你的例子中,键Sample是一个对象,而不是我的例子中的原语。严格地说,我需要一个快速高效的散列函数,其中结果是数组的索引,键是一个short to stay in Java terminologyshort是一个原始数据类型。原始数据类型不能用作键-只能使用它们各自的包装类;这些包装器已经定义了hashcode。您是否需要一个接受任何类型T并返回哈希的哈希函数?我们是否误读了对方?问题不在于Java本身。这是更基本的。即使在Java中,我的密钥也不必包装在对象中,除非我坚持使用HashMap的标准JDK实现。但是还有很多其他的实现,比如fastutils、Trove、Koloboke、HPPC等等,它们都允许密钥成为原语。我可以使用其中的一个,但我认为我的用例限制性很强,我可以做得更好。但也许没有。我对数学了解不够,说不出话来。FastUtils和Koloboke似乎都使用了一个3哈希函数。我想说的是,我可以使用那些伟大的库中的一个,但我希望有一个更简单、更快的解决方案,因为我可以将我的用例缩小到一些限制性的东西。这些库也必须满足更一般化的情况。哦,我假设我们是用Java术语说话的,因为您的代码中有关于模的Java语法的注释。那是我这边的误解。在这种情况下,我能给你的最起码的答案是不使用模运算,因为模运算与其他算术运算相比,是一种相对缓慢的运算。
int index = key * random & (rest_table_size_power_of_2 - 1);