哈希碰撞究竟是什么

时间:2017-08-21 11:11:59

标签: java collections collision hash-collision

HashMap中的哈希碰撞或哈希碰撞不是一个新主题,我遇到了几个博客和讨论板,解释了如何产生哈希碰撞或如何以模糊和详细的方式避免它。我最近在一次采访中遇到了这个问题。我有很多事要解释,但我认为很难准确地给出正确的解释。对不起,如果我的问题在这里重复,请告诉我确切的答案:

  1. Hash Collision究竟是什么 - 它是一个特征,或者是一个错误的常见现象,但是很好避免?
  2. 究竟是什么导致哈希碰撞 - 自定义类的错误定义' hashCode()方法,或者equals()方法不被覆盖而不完全覆盖hashCode()方法,或者它不是由开发人员决定的,许多流行的java库也有类可以引起哈希碰撞?
  3. 当Hash Collision发生时,是否出现任何问题或意外?我的意思是,为什么我们应该避免Hash Collision呢?
  4. 在对象启动期间,Java是否生成或至少尝试为每个类生成唯一的hashCode?如果不是,单独依靠Java来确保我的程序不会遇到JRE类的Hash Collision是正确的吗?如果不对,那么如何避免使用像String这样的最终类的哈希映射的哈希冲突?
  5. 如果您能为这些问题中的一个或所有问题分享答案,我会非常感激。

5 个答案:

答案 0 :(得分:8)

  

Hash Collision到底是什么 - 它是一个错误的特征或普遍现象,但是很好避免?

这是一个功能。它产生于hashCode的本质:从大值空间到更小值空间的映射。根据设计和意图,会发生碰撞。

  

究竟是什么导致Hash Collision - 自定义类'hashCode()方法的错误定义,

糟糕的设计可能会使情况变得更糟,但它在这个概念中是流行的。

  

OR,在不完全覆盖hashCode()方法的情况下,使equals()方法不被覆盖,

没有

  

OR是不是由开发人员负责,许多流行的java库也有可能导致Hash Collision的类?

这没有多大意义。哈希迟早会发生碰撞,而糟糕的算法可能会更快地发生。就是这样。

  

当Hash Collision发生时,是否出现任何问题或意外?

如果哈希表写得很好,那就不行了。哈希冲突只意味着hashCode不是唯一的,这会让你调用equals(),而且重复的次数越多,性能越差。

  

我的意思是我们应该避免Hash Collision吗?

你必须权衡计算的简易性和价值的传播。没有单一的黑白答案。

  

Java生成或至少尝试在对象启动期间为每个类生成唯一的hasCode吗?

没有。 “唯一哈希码”是一个矛盾。

  

如果不是,单独依靠Java来确保我的程序不会遇到JRE类的Hash Collision是否正确?如果不对,那么如何避免使用像String这样的最终类作为键的哈希映射的哈希冲突?

这个问题毫无意义。如果您正在使用String,那么您对哈希算法没有任何选择,并且您还使用了一个类,该类的hashCode已被专家服务了20年或更长时间。

答案 1 :(得分:3)

实际上我认为哈希冲突是正常的。让我们来谈谈一个思考的案例。我们有1000000个大数字(x的集合S),比如x在2 ^ 64。现在我们想为这个数字集做一个地图。让这个数字集S映射到[0,1000000]。

但是怎么样?用哈希!!

定义一个散列函数f(x)= x mod 1000000.现在S中的x将被转换为[0,1000000],好的,但是你会发现S中的许多数字将转换成一个数字。例如。数字k * 1000000 + y都将位于y中,因为(k * 1000000 + y)%x = y。所以这是一个哈希冲突。

如何应对碰撞?在我们上面讨论的这种情况下,由于数学计算具有一定的可能性,因此很难界定碰撞。我们可以找到一个更复杂,更好的哈希函数,但不能肯定地说我们消除了碰撞。我们应该努力寻找更好的哈希函数来减少哈希冲突。因为哈希冲突会增加时间成本,所以我们使用哈希来查找内容。

简单地说,有两种方法可以处理哈希冲突。链接列表是一种更直接的方式,例如:如果上面两个数字在hash_function之后得到相同的值,我们从这个值桶创建一个链表,并且所有相同的值都被赋予值的链表。另一种方法是找到后一个数字的新位置。例如,如果数字1000005占据了5中的位置,当2000005获得值5时,它不能位于第5位,然后继续前进并找到空位置。

对于最后一个问题:在对象启动期间,Java是否生成或至少尝试为每个类生成唯一的hashCode?

Object的哈希码通常通过将对象的内部地址转换为整数来实现。因此,如果使用Object的hashcode(),则可以认为不同的对象具有不同的哈希码。

答案 2 :(得分:1)

  

Hash Collision究竟是什么 - 它是一个特殊的,或者是普遍的现象,这是错误的但是很好避免?

  • 哈希冲突就是那个字段哈希码在对象上的冲突......
  

究竟是什么导致哈希碰撞 - 自定义类的错误定义' hashCode()方法,OR保留equals()方法   未完全覆盖,同时不完美地覆盖hashCode()方法   单独,或者它不是由开发人员和许多流行的Java   库还有可能导致哈希冲突的类?

  • 不,碰撞可能会发生,因为它们是由数学概率决定的,在这种情况下,生日悖论是解释这一点的最好方法。
  

当Hash Collision发生时,是否出现任何问题或意外?我的意思是,为什么我们应该避免哈希碰撞?

  • 不,java中的String类是非常发达的类,你不需要搜索太多来找到碰撞(检查这个字符串的编码" Aa"和" BB&#34 ; - >两者都与2112发生碰撞)

总结: 哈希码冲突是无害的你知道那是什么,为什么与用于证明相等的id相同

答案 3 :(得分:1)

  

Hash Collision到底是什么 - 它是一个特征还是普遍现象   这是错误的,但很好避免?

两者都没有...这是一种普遍现象,但没有错误地做,这是很好的避免。

  

究竟是什么导致Hash Collision - 自定义的错误定义   class'shashCode()方法,OR保留equals()方法   未完全覆盖,同时不完美地覆盖hashCode()方法   单独,或者它不是由开发人员和许多流行的Java   库还有可能导致Hash Collision的类吗?

通过设计你的hashCode()方法很糟糕,你可以产生太多的冲突,让你的equals方法不被覆盖不应该直接影响冲突的数量,许多流行的java库都有可以导致冲突的类(几乎所有的类实际上都是)。

  

当Hash Collision发生时,是否出现任何问题或意外?一世   是否有任何理由我们应该避免哈希碰撞?

性能下降,这是避免它们的原因,但程序应该继续有效。

  

Java是否生成或至少尝试生成唯一的hashCode per   在对象启动期间的类​​?如果不是,依靠Java是否正确   单独确保我的程序不会遇到Hash Collision   JRE课程?如果不对,那么如何避免哈希冲突   像String这样的最终类的哈希映射?

Java在对象初始化期间不会尝试生成唯一的哈希代码,但它具有hashCode()和equals()的默认实现。默认实现用于了解两个对象引用是否指向同一实例,并且不依赖于对象的内容(字段值)。因此,String类有自己的实现。

答案 4 :(得分:0)

  1. 当两个单独的值产生您可能知道的相同哈希时,会发生哈希冲突。哈希为给定的值产生固定数量的字符,因此尽管有微小概率,但总有两个值产生相同哈希的可能性。所以我们可以说它带有哈希函数本身。在使用它时,我们理解两个值可能产生相同的哈希的事实。尽管计算哈希冲突很困难,但如果我没记错的话,谷歌几个月前已成功计算出一次SHA-1碰撞。 https://www.theregister.co.uk/2017/02/23/google_first_sha1_collision/

  2. 我不认为我对此有所了解。

  3. 是。假设某种函数我们计算一个哈希来运行它。因此,在某些情况下,如果一个人在不知不觉中产生哈希冲突,那么该特定功能将会运行。这可能会导致系统出现故障或失败。