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

HashMap在Java中的实现。桶指数是如何计算的?

靳彦
2023-03-14

我正在看HashMap在Java中的实现,在某一点上卡住了。
如何计算indexFor函数?

static int indexFor(int h, int length) {
   return h & (length-1);
}

谢谢

共有3个答案

农星华
2023-03-14
匿名用户

上面的答案很好,但我想进一步解释为什么Java可以使用indexFor来创建索引

例如,我有一个类似这样的HashMap(这个测试是在Java7上进行的,我看到Java8对HashMap做了很多更改,但我认为这个逻辑仍然非常好)

// Default length of "budget" (table.length) after create is 16 (HashMap#DEFAULT_INITIAL_CAPACITY)
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("A",1); // hash("A")=69, indexFor(hash,table.length)=69&(16-1) = 5
hashMap.put("B",2); // hash("B")=70, indexFor(hash,table.length)=70&(16-1) = 6
hashMap.put("P",3); // hash("P")=85, indexFor(hash,table.length)=85&(16-1) = 5
hashMap.put("A",4); // hash("A")=69, indexFor(hash,table.length)=69&(16-1) = 5
hashMap.put("r", 4);// hash("r")=117, indexFor(hash,table.length)=117&(16-1) = 5

您可以看到带有键“A”的条目索引和带有键“P”的对象以及带有键“r”的对象具有相同的索引(=5)。下面是我执行上面代码后的调试结果

图中的表格在这里

public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable {
    transient HashMap.Entry<K, V>[] table;
    ...
}

=

static class Entry<K, V> implements java.util.Map.Entry<K, V> {
        ...
        HashMap.Entry<K, V> next;
}

您可以通过阅读HashMap中的代码来再次验证它。

与现在一样,您可以认为HashMap永远不需要更改大小(16),因为indexFor()总是返回值

 if (this.size >= this.threshold ...) {
      this.resize(2 * this.table.length);

HashMap将在size

什么是threadhold<代码>Thread固定计算如下

static final int DEFAULT_INITIAL_CAPACITY = 16;
static final float DEFAULT_LOAD_FACTOR = 0.75F;
...
this.threshold = (int)Math.min((float)capacity * this.loadFactor, 1.07374182E9F); // if capacity(table.length) = 16 => threadhold = 12

尺寸是多少<代码>大小计算如下
当然,size这里不是表格。长度
当您将新条目放入HashMapHashMap时,需要创建新条目(请注意,HashMap键相同时不创建新条目,它只会覆盖现有条目的新值),然后size

void createEntry(int hash, K key, V value, int bucketIndex) {
    ...
    ++this.size;
}

希望能有所帮助

劳灵均
2023-03-14

它不是在计算散列,而是在计算桶。

表达式h

萧玮
2023-03-14

散列本身由您试图存储的对象的hashCode()方法计算。

您在这里看到的是根据哈希h计算存储对象的“桶”。理想情况下,为了避免冲突,您将拥有与h最大可实现值相同数量的桶——但这可能太需要内存了。因此,您通常拥有较少数量的桶,有冲突的危险。

如果h是1000,但是您的底层数组中只有512个桶,您需要知道将对象放在哪里。通常,对h进行mod操作就足够了,但是这太慢了。考虑到HashMap的内部属性,底层数组的桶数总是等于2^n,Sun的工程师可以使用h的想法

例:

     hash h: 11 1110 1000  -- (1000 in decimal)
   length l: 10 0000 0000  -- ( 512 in decimal)
      (l-1): 01 1111 1111  -- ( 511 in decimal - it will always be all ONEs)
h AND (l-1): 01 1110 1000  -- ( 488 in decimal which is a result of 1000 mod 512)

 类似资料:
  • 问题内容: 我正在研究Java 的实现,只停留在一点。 该函数如何计算? 谢谢 问题答案: 它不是在计算 哈希 ,而是在计算 存储桶 。 表达确实逐位上使用,这是像一个位掩码,以便仅返回的低位比特,从而使得对于一个超高速变体。

  • 问题内容: 在一次采访中,我被要求计算内存使用量,如果其中有200万个项目,则估计将消耗多少内存。 例如: 映射是这样的。 我如何估计Java中此HashMap对象的内存使用情况? 问题答案: 简短的答案 为了找出对象的大小,我将使用探查器。例如,在YourKit中,您可以搜索对象,然后获取它以计算其深度大小。这将使您很清楚地知道如果对象是独立的,则使用多少内存,并且该对象的大小是保守的。 怪癖

  • 问题内容: 说我有阵列 数组的长度为20,但计数为0。如何获取计数? 问题答案: “计数”是什么意思?具有非零值的元素数量?您只需要数一下。 有 没有区别 数组和一个已之间 明确地 设置与零个值。例如,这些数组是无法区分的: Java中的数组始终具有固定大小-可通过字段访问。没有“当前使用的阵列数量”的概念。

  • 本文向大家介绍java实现水仙花数的计算,包括了java实现水仙花数的计算的使用技巧和注意事项,需要的朋友参考一下 看到标题java实现水仙花数,首先先要知道什么是水仙花数,具体了解一下 所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数 列如153=1*1*1+5*5*5+3*3*3  那么153就是水仙花数,首先是分析需要的功能,首先他是一个3位数。 那值一定在100-1000之间,必定

  • 问题内容: 我有一个Java客户端正在调用Web服务操作,该操作将证书“ thumbprint”作为参数。我相信指纹是证书的公钥的某种SHA16哈希,采用十六进制字符串格式,但是我不确定。 .NET框架似乎包括一种获取此值的简单方法(X509Certificate2.Thumbprint属性)。在Windows中查看.cer文件的属性也会显示指纹,如下所示: 因此,我的问题是:如果我有java.s

  • 我正在努力为下面给出的学生类编写合适的hashCode函数。 1)我认为hashCode应该足够好,这样两个不同对象的hashCode就不会相互冲突。 观察:对于这个实现,当我调试并检查“HashMap的内部表对象”类时,我发现HashMap中的每个条目都分配了不同的bucket位置。 问题:在每个索引处有一个桶(列表/树)的目的是什么。 实施: 2)如果我允许hashCode冲突: 观察:对于这