Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 对散列码的理解_Java_Hash - Fatal编程技术网

Java 对散列码的理解

Java 对散列码的理解,java,hash,Java,Hash,哈希函数是实现哈希表的重要工具。我在java中知道这一点 对象具有其哈希代码,该代码可能由弱哈希函数生成 下面是一段“补充哈希函数” 静态整数散列(对象x){ int h=x.hashCode(); h+=~(h>>14); h+=(h>>10); 返回h; } 有人能解释一下散列算法的基本思想吗 ? 要生成非重复整数?如果是这样的话,它们是如何按位排列的 操作使它成为可能?您通常尝试使用散列算法将一个大的搜索键转换为一个小的非负数,这样您就可以在某个表中查找相关记录,并且比M log2 N(

哈希函数是实现哈希表的重要工具。我在java中知道这一点 对象具有其哈希代码,该代码可能由弱哈希函数生成

下面是一段“补充哈希函数”

静态整数散列(对象x){
int h=x.hashCode();
h+=~(h>>14);
h+=(h>>10);
返回h;
}
有人能解释一下散列算法的基本思想吗 ? 要生成非重复整数?如果是这样的话,它们是如何按位排列的
操作使它成为可能?

您通常尝试使用散列算法将一个大的搜索键转换为一个小的非负数,这样您就可以在某个表中查找相关记录,并且比M log2 N(其中M是“比较”的成本,N是“表”中的项数)更快地执行此操作典型的二进制搜索(或树搜索)

如果您有幸拥有一个完美的散列,那么您知道(已知!)密钥集的任何元素都将被散列为一个唯一的、不同的值。对于需要查找语言关键字的编译器来说,完美散列最为重要

在现实世界中,存在不完全散列,其中多个键都散列到相同的值。没关系:现在只需将密钥与一小部分候选匹配项(散列到该值的匹配项)进行比较,而不是与一大部分(完整表)进行比较。传统上,这些小装置被称为“桶”。使用散列算法选择一个bucket,然后为bucket本身使用其他一些可搜索的数据结构。(如果已知或安全地预计存储桶中的元素数量非常少,那么线性搜索并非不合理。二元搜索树也是合理的。)


您的示例中的逐位操作看起来很像签名分析移位寄存器,它试图将长的唯一位模式压缩为短的、仍然唯一的模式。

哈希函数是任何定义良好的过程或数学函数,用于将大的、可能大小可变的数据量转换为小数据,通常是单个整数,可以用作数组的索引。散列函数返回的值称为散列值、散列码、散列和、校验和或简单的散列。()


使用更多“人类”语言的对象哈希是一个基于对象属性的简短紧凑的值。也就是说,如果您有两个不同的对象,您可以期望它们的散列值是不同的。好的散列算法为不同的对象生成不同的值

这段代码试图通过混合位来提高散列值的质量

总体效果是,对于给定的x.hashCode(),您有望在整个整数范围内获得更好的散列值分布。如果您从一个糟糕的哈希代码实现开始,然后以这种方式改进哈希代码,那么某些算法的性能将得到提高


例如,Java中一个普通整数的hashCode()只返回整数值。虽然这在很多方面都很好,但在某些情况下,您需要一个更好的哈希代码,因此通过这种函数使用哈希代码可以显著提高性能。

基本上,您试图通过哈希函数实现的目标是,给定要进行哈希处理的特定项,使哈希代码中的所有位有大约50%的几率关闭或打开。这样,不管哈希表有多少个“bucket”(或者换言之,为了确定bucket数而取多少个底部位)——如果每个位都是尽可能随机的,那么一个项总是被分配给一个基本随机的bucket

现在,在现实生活中,许多人使用的散列函数不是很好。它们在某些位上有一些随机性,但不是全部。例如,想象一下,如果你有一个哈希函数,其位6-7是有偏差的——比如在一个对象的典型哈希代码中,它们有75%的几率被设置。在这个虚构的例子中,如果我们的哈希表有256个bucket(即bucket编号来自哈希代码的0-7位),那么我们就抛弃了位8-31中确实存在的随机性,并且较小部分的bucket将趋向于被填充(即设置了位6和位7的数字)


补充散列函数基本上尝试将散列码中的任何随机性分散到更多的位上。因此,在我们假设的例子中,我们的想法是,来自比特8-31的一些随机性将与较低的比特混合,并稀释比特6-7的偏差。它仍然不是完美的,但比以前更好。

如果要生成哈希表,那么在编写哈希函数时,您希望了解的主要内容是确保一致性,而不一定要创建完全唯一的值

例如,如果您有一个大小为10的哈希表,则不希望哈希函数多次返回3的哈希值。否则,该特定存储桶将强制执行O(n)的搜索时间。您需要一个哈希函数,使其返回,例如:1、9、4、6、8。。。并确保你的水桶没有一个比其他水桶重得多


对于您的项目,我建议您使用著名的散列算法,如MD5或更好的SHA,并使用您需要的前k位,然后丢弃其余的。这些都是经过时间考验的函数,作为程序员,你最好聪明地使用它们。

只要你遵守文档中描述的,它可以是你想要的任何东西,用我自己的话说就是:

  • 如果对一个对象调用100(N)次hashCode,所有时间都必须返回相同的值,至少在该程序执行期间(后续程序执行可能返回不同的值)
  • 如果
    o1.equals(o2)
    为true,则
    o1.hashCode()==o2.hashCode()
    也必须为true
  • 如果
    o1.equals(o2)
    为false,则
    o1.hashCode()==o2.hashCode()
    可能为t
    static int hash(Object x) {
        int h = x.hashCode();
    
        h += ~(h << 9);
        h ^=  (h >>> 14);
        h +=  (h << 4);
        h ^=  (h >>> 10);
        return h;
    }