当前位置: 首页 > 知识库问答 >
问题:

如何有效地实现hashCode()单链表节点在Java?

申屠亦
2023-03-14

Eclipse通过以下方式为单链表的Node类实现hashCode()函数

class Node{
    int val;
    Node next;

    public Node(int val){
        this.val = val;
        next = null;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((next == null) ? 0 : next.hashCode());
        result = prime * result + val;
        return result;
    }
}

现在,节点的hashCode()依赖于它后面的节点的哈希代码。

因此,hashCode()的每次调用都将在链表长度上花费摊销的线性时间。因此,使用哈希集

解决这一问题的一种方法是将hashCode的值缓存在变量中(称之为hash),以便只计算一次。但是即使在这种情况下,一旦任何节点的val被更改,散列也将变得无效。同样,修改跟随当前节点的节点的hashCode需要线性时间。

那么,对于这样的链表节点,有什么好的实现哈希的方法呢?


共有2个答案

松灿
2023-03-14

你必须问问自己什么样的散列质量对你来说是有价值的。唯一的限制是确保具有相同顺序的相同编号的另一个列表具有相同的哈希。这是通过使用contant数和第一个数以及限制5个数来实现的。多少数字对您有意义取决于数据的结构。例如,如果始终存储从1开始的连续升序数字,并且差值仅为长度,则很难进行优化。如果它在int的整个范围内是完全随机的,那么第一个数字将很好地完成这项工作。我会说,有多少数字能为你提供最佳的比率是通过测量得出的。

最后,您需要的是碰撞(放在同一个桶中的对象)和计算时间之间的良好比例。生成的实现通常试图最大化计算时间,为开发人员提供很大的改进空间

关于包含值的变化:java.util.HashSet(分别是它持有的HashMap)将计算它自己的哈希值,并缓存它。因此,如果HashSet中包含的对象一旦更改到哈希更改的程度,就无法再次找到。

沙小白
2023-03-14

读到你的问题时,我的第一个想法是:LinkedList做什么?深入研究源代码,我们发现在内部链接列表上没有定义hashCode()equals()。节点类(链接到源)。

为什么这有意义?节点通常是内部数据结构,仅对列表本身可见。它们不会被放入集合或任何其他需要比较相等性和哈希代码的数据结构中。外部代码无法访问它们。

你在问题中说:

因此,使用哈希集

但我认为您没有必要将节点放置在这样的数据结构中。根据定义,您的节点将相互链接,并且不需要额外的类来促进这种关系。除非您计划在列表之外公开这个类(这是不必要的),否则它们永远不会出现在HashSet中。

我建议您遵循链接列表。节点建模并避免在节点上创建这些方法。外部列表可以根据节点中存储的值(而不是节点本身)来确定其哈希代码和相等性,这就是LinkedList的工作方式-请参见AbstractList(链接到源代码)。

源代码链接指向OpenJDK源代码,但在本例中,它们与Oracle JDK提供的源代码相同

 类似资料:
  • 在C很新,很抱歉提前听起来很没有经验... 我希望通过将节点存储在静态分配的数组中来实现列表抽象数据类型,而不使用malloc()或free()。每个列表元素都是一个节点,可以容纳一个“项”。我需要能够使用next和previous遍历节点,并具有“current”、“tail”、“head”的概念。 还有两个数组。。。一个指向“头”的指针数组,因此每个头都有一个“节点”数组。我还需要能够将当前项

  • C语言面向对象编程(五):单链表实现 前面我们介绍了如何在 C 语言中引入面向对象语言的一些特性来进行面向对象编程,从本篇开始,我们使用前面提到的技巧,陆续实现几个例子,最后呢,会提供一个基本的 http server 实现(使用 libevent )。在这篇文章里,我们实现一个通用的数据结构:单链表。 这里实现的单链表,可以存储任意数据类型,支持增、删、改、查找、插入等基本操作。(本文提供的是完

  • 问题内容: 我想知道是否有人可以详细解释 在以下哈希码实现中执行(由eclipse生成,但与有效Java相同): 谢谢! 问题答案: 基本上,它对long的高32位与低32位进行异或。这是分解版本: 回答您的评论:您有一个long值,必须将其转换为int才能作为哈希的一部分(结果必须仅为32位)。你打算怎么做?您 可以 只使用低32位-但这意味着 仅 高32位的更改将被忽略,这不会使其成为一个很好

  • 我在以递归方式从循环单链表中删除单个节点/值时遇到了一些问题(当然,如果可能的话)。我的代码只从中间删除,而不是从第一个或最后一个地方删除。 在以递归方式删除其中一个连接后,我不知道如何建立连接。我的意思是,如果我要删除第一个元素,那么我需要将最后一个节点连接到下一个节点。 这是我的代码: 参数和返回: 查找尾部功能:

  • 问题内容: hashCode()如何实现? 我的假设是它将对象存储位置用作运行哈希函数的初始数字(种子)。然而,这种情况并非如此。 我还研究了Hash:它在内部如何工作?但它不能回答我的问题。 是的,我可以下载SDK,但是在执行此操作并查看代码之前,也许其他人已经知道了。 谢谢 :) 编辑: 我知道它应该被覆盖等等,所以请尝试保持话题:) 问题答案: 当然,它是特定于实现的,但是通常,对象的哈希码

  • 我在谷歌上搜索了这个,但他们都在谈论“交换节点而不交换数据”。 我尝试自己编写一个交换节点方法: 如您所见,和相互更改,但打印结果不交换。如何交换两个节点及其数据? 编辑:下面的完整示例