欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

再对一个相等的对象甚至同一个对象 CAD加密 的查询会失败!这个数据结构会计算当前的哈希码

点击: 次  来源:宝鼎软件 时间:2017-09-19

原文出处: 开源中国

相等 和 Hash Code

从一般角度来看,Equality 是不错的,可是 hash code 更则具能力性。假如我们在 hash code上多下点工夫,我们就能相识到 hash code 就是用在细微处去晋升机能的。

大部门的数据布局利用equals去查抄是否他们包括一个元素。譬喻:

List<String> list = Arrays.asList("a", "b", "c");
boolean contains = list.contains("b");

这个变量 contains 是true。因为他们是相等的,固然b的实例化(instance)固然不完全一样(再说一次,忽略String interning)。

将通报给 contains 的实例与每个元素举办较量很挥霍时间。还好,整个这类数据布局利用了一种更高效的要领。它不会将请求的实例与每个元素较量,而是利用捷径,找到大概与之相等的实例,然后只较量这几项。

这个捷径就是哈希码——从工具计较出来的一个能代表该工具的整数值。与哈希码沟通的实例不必相等,但相等的实例必然有沟通的哈希码。(可能说应该有,我们稍后会对这个问题举办简朴接头)。这类的数据布局经常利用这种技能定名,在名称中插手 Hash 以便识别,个中最具代表性的就是 HashMap。

一般环境下它们会这样举办:

  • 添加一个元素的时候,利用它的哈希码来计较存放在内部数组(称为桶)中的位置(序号)。
  • 另一个不等同的元素假如具有沟通的哈希码,它会被放在同一个桶中,与本来谁人放在一起,好比把它们放在一个列表中。
  • 假如通报一个实例给 contains 要领,会先计较它的哈希码来找到桶,只有同一个桶中的元素需要与这个实例举办较量。
  • 利用这种要领实现 contains 的环境很少,在抱负的状态下基础不需要 equals 较量。

    将 equals、hashCode 界说在 Object 中。

    关于哈希的一些思考

    假如把 hashCode 作为一种快捷方法取决于其是否相等,那么只有一件工作我们需要体贴:相等的工具应该有一致的哈希码。

    这也是为什么,假如我们覆写 equals 要领,就必需建设一个匹配的 hashCode 实现!另外,实现 equal 应该是依据我们的实现而实现的,这大概会导致没有沟通的哈希码,因为他们利用的是 Object 的实现。

    hashCode 约定

    从原文档引用:

    对付 hashCode 的一般约定:

  • Java 应用措施中,任何时候对同一工具多次挪用 hashCode 要领,都必需一直返回同样的整数,对它提供的信息也用于工具的相等较量,且不会被修改。这个整数在两次对同一个应用措施的执行不中不需要保持一致。
  • 假如两个工具通过 equals(Object) 要领来较量相等,那么这两个工具的 hashCode 要领必需发生同样的整型功效。
  • 假如两个工具通过 equals(Object) 要领较量功效不等,这两个工具的 hashCode 不必发生同不整型功效。然而,开拓者应该相识对不等的工具发生差异的整型功效有助于提高哈希表的机能。
  • 第一条反应了 equals 的一致性。第二条是我们在上面提到的要求。第三条告诉了我们下面要接头的一个重要细节。

    实现 hashCode

    Person.hashCode 有个很简朴的实现:

    @Override
    public int hashCode() {
    return Objects.hash(firstName, lastName);
    }

    通过计较相关字段的哈希码,再把这些哈希码组合起来获得 person 的哈希码。它们用 Object 的东西函数 hash 来参加计较。

    选择字段

    然而什么字段才是相关的?这些要求有助于答复这个问题:假如相等的工具必需有沟通的哈希码,那么在计较哈希码的时候就不该该利用那些不消于相等性查抄的字段。(不然,假如两个工具只有那些字段差异的话,它们会相等但哈希码差异。)

    所以用于计较哈希码的那些字段应该是用于相等性较量的那些字段的子集。默认环境下,它们会利用沟通的字段,但有几个细节需要思量。

    一致性

    第一是一致性要求。它应该颠末很是严格的计较。假如有字段发生了变革,哈希码也应该答允变革(对付可变类来说,这往往是不行制止的),依赖哈希的数据布局并未筹备应付这种环境。

    正如我们在上面看到的那样,哈希码用于确定一个元素的桶,可是假如哈希相关的字段产生变革,并不会当即从头计较哈希码,并且内部的数组也不会更新。

    这就意味着,再对一个相等的工具甚至同一个工具的查询会失败!这个数据布局管帐算当前的哈希码,软件开发,这个哈希码与实例存入时的哈希码并不沟通,这直接导致找错了桶。

    小结:最好不要用可变的字段来计较哈希码!

    机能