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

如何在Java中高效地为单链表节点实现hashCode()?,java,hash,linked-list,singly-linked-list,Java,Hash,Linked List,Singly Linked List,Eclipse通过以下方式为单链表的节点类实现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;

Eclipse通过以下方式为单链表的节点类实现
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()
的每次调用都将在链表长度上花费摊销的线性时间。因此,使用
HashSet
将变得不可行

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


那么,对于这样一个链表节点,有哪些好的实现哈希的方法呢

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

为什么这有意义?嗯,节点通常是内部数据结构,仅对列表本身可见。它们不会被放入集合或任何其他数据结构中,因为在这些数据结构中,比较等式和散列码是必要的。没有外部代码可以访问它们

你在问题中说:

因此,使用
HashSet
将变得不可行

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

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


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

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


关于所包含值的更改:java.util.HashSet(分别是它所持有的HashMap)将在您的hash上计算它自己的hash,并缓存它。因此,如果哈希集中包含的对象在其哈希值发生更改后无法再次找到

那么,只需
返回val,因为它是一个
int
;尽管这取决于您如何实现
.equals()
,但问题是节点代表整个列表,因此它的哈希代码依赖于整个列表。请这样考虑-如果您不说
ll1.equals(ll2)
true
,那么您肯定不希望它们的
hashCode()
是相同的。因此,以尊重合同的方式实施它。@Nikunbanka以下两个链表“相等”吗<代码>[x]->[x]->NULL
[x]->[x]->[x]->[x]->NULL
;它们只包含
x
,但其中一个更长。想想这个问题,无论是谁否决了这个问题:这是一个完全有效的考虑,值得我们深思。绝对不值得投反对票。