identityhashcode

ws51t4hk  于 2021-06-30  发布在  Java
关注(0)|答案(3)|浏览(251)

在实施细则中 HashMap ,我可以阅读:

When using comparators on insertion, to keep a
 * total ordering (or as close as is required here) across
 * rebalancings, we compare classes and identityHashCodes as
 * tie-breakers.

如果我有常数 hashCode 很好 equals 我的类没有实现 Comparable 它究竟将如何打破联系,树将如何建造?
我是说-水桶会变成一棵树 System.identityHashCode 打破平局。那我就给你打电话 containsKey 方法具有不同的示例(将具有相同的 hashCode 以及 a.equals(b) == true )会有不同的结果 identityHashCode 那么,有没有可能树被错误的节点(从左到右)遍历而找不到键呢?
我是错过了什么还是这是正常的行为?

sd2nnvve

sd2nnvve1#

不,您实际上是根据 System::identityHashCode 但是在这个bucket中,仍然有一些条目具有相同的hashcode(不是相同的,只是重要的部分)。
所以当你寻找某样东西的时候,它有时必须同时考虑两者 left 以及 right ,没办法,就这么简单。

g2ieeal7

g2ieeal72#

铲斗将使用 identityHashCode 但查找只使用哈希码和 compare() 电话(如果有)。这意味着它有时需要扫描节点的两个子树。
查找逻辑如下所示

do {
  if (... keys are equal or can be compared ...) {
    // Go left, right or return the current node
    ...
  } else if ((q = pr.find(h, k, kc)) != null)
    // Search the right subtree recursively
    return q;
  else
   // Go to the left subtree
   p = pl;
} while (p != null);

看到了吗http://hg.openjdk.java.net/jdk10/jdk10/jdk/file/ffa11326afd5/src/java.base/share/classes/java/util/hashmap.java#l1901 请注意 tieBreakOrder() (负责比较的方法) identityHashCode 中的任何位置都不会调用s find() .

myzjeezk

myzjeezk3#

在引用的部分之前,我们已经解释了标识哈希码基绑定中断的动机:
hashmap.java,第212行:


* When bin lists are treeified, split, or untreeified, we keep
* them in the same relative access/traversal order (i.e., field
* Node.next) to better preserve locality, and to slightly
* simplify handling of splits and traversals that invoke
* iterator.remove. When using comparators on insertion, to keep a
* total ordering (or as close as is required here) across
* rebalancings, we compare classes and identityHashCodes as
* tie-breakers.

因此,按标识哈希码排序提供了一个稳定的排序,以帮助实现拆分和 Iterator.remove() 操作(必须支持一致地继续遍历)。
如本答案所述,它不用于查找操作,正如您在问题中所说的,两个相等的对象可能具有不同的标识码。对于具有相同哈希代码且未实现 Comparable ,没有办法遍历它们并通过 equals .

相关问题