Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hashmap内部_Java_Arrays_Hashmap - Fatal编程技术网

Java Hashmap内部

Java Hashmap内部,java,arrays,hashmap,Java,Arrays,Hashmap,我对JavaHashMap类没有什么疑问。我的理解是 transient Entry[] table; 表数组将根据hashCode()的值保存数据。我需要知道这个数组何时初始化。数组长度是基于我们在HashMap初始化期间定义的容量,还是基于调用构造函数时未定义的默认容量16 哈希代码如何缩放到数组索引?例如,如果hashcode有一个巨大的值,那么如何将其缩放到数组索引(如10、20) 我已经读到,当达到阈值时,将发生重新灰化。例如,在默认情况下,当16是容量,0.75是负载系数时,阈值

我对Java
HashMap
类没有什么疑问。我的理解是

 transient Entry[] table;
表数组将根据
hashCode()
的值保存数据。我需要知道这个数组何时初始化。数组长度是基于我们在
HashMap
初始化期间定义的容量,还是基于调用构造函数时未定义的默认容量16

哈希代码如何缩放到数组索引?例如,如果hashcode有一个巨大的值,那么如何将其缩放到数组索引(如10、20)


我已经读到,当达到阈值时,将发生重新灰化。例如,在默认情况下,当16是容量,0.75是负载系数时,阈值为
16*0.75=12
。一旦添加12项,将进行再灰化,容量将增加。这是否意味着
数组大小增加了?

因为你的帖子有很多问题,我将列举你的问题作为我答案的一部分。另外,请注意,我要去寻找我的答案

public HashMap(int initialCapacity, float loadFactor) {
     if (initialCapacity < 0)
         throw new IllegalArgumentException("Illegal initial capacity: " +
                                            initialCapacity);
     if (initialCapacity > MAXIMUM_CAPACITY)
         initialCapacity = MAXIMUM_CAPACITY;

     if (loadFactor <= 0 || Float.isNaN(loadFactor))
         throw new IllegalArgumentException("Illegal load factor: " +
                                            loadFactor);

     // Find a power of 2 >= initialCapacity
     int capacity = 1;
     while (capacity < initialCapacity)
         capacity <<= 1;
     this.loadFactor = loadFactor;
     threshold = (int)(capacity * loadFactor);
     table = new Entry[capacity];
     init();
 }
  • 问:我需要知道这个数组何时被初始化。
    答:
    数组仅在数据首次输入映射时初始化(例如
    put()
    方法调用)。它不会作为映射本身实例化的一部分发生,除非调用复制构造函数,或者映射被反序列化为对象
  • Q:数组长度是基于我们在
    HashMap
    初始化期间定义的容量,还是基于调用构造函数时未定义的默认容量16?
    答:正确,
    数组的长度基于传递给构造函数的初始容量。当未指定初始容量且调用默认构造函数时,将使用默认容量
  • 问:哈希代码如何缩放到数组索引?
    答:有关实际执行此操作的代码,请参阅。基本上,代码采用非常大的散列值,并对表的最后一个元素索引执行
    按位and
    。这将有效地随机化键/值对与
    数组的位置。例如,如果散列值是333(在基数2中是101001101),并且
    数组大小是32(100000),那么最后一个元素索引将是31(11111)。因此,选择的索引将是
    11111&101001101==01101==13
  • 问:我读到,当达到阈值时,会发生重新灰化。。。这是否意味着表数组大小增加了?
    A:差不多,是的。当超过
    阈值时,将调整表的大小。请注意,通过调整大小,不会修改现有的
    数组。而是创建一个新的
    数组,其容量是第一个
    数组的两倍。有关详细信息,请参阅

  • 谢谢你,乔纳森。我几乎明白了。只是另一个问题,即与Q:3有关的问题。在这个示例中,您已经清楚地解释了如何将hashcode 333放入32长度的数组中。所以它意味着任何hashcode值都可以放入32长度的数组中。那么,调整大小的必要性是什么呢。在索引冲突的情况下,碰撞对象将存储在同一索引元素中。我说得对吗?在什么基础上调整大小?好问题。是的,可以在同一索引中存储多个元素,因为
    数组的类型是
    HashMap
    -
    节点
    的内部类型,该节点引用了可能的
    下一个
    节点。因此,以这种方式,固定大小的
    可以具有无限数量的条目。当键值对的数量(即
    HashMap
    中的
    大小
    字段)超过
    阈值
    值(即
    数组的大小乘以
    加载因子
    )时,通常会触发调整大小。因此,在调整大小时,会重新排列对象吗?在上面的示例中,当表大小为32时,占用哈希代码333的对象将位于第13位。在调整大小时,大小会增加一倍,所以现在的大小将变为64。为了避免混淆,我们再次考虑它会加倍到128,因为大小64也占据13的位置。与128,1111111和101001101==1001101==77。它会被存储在77位吗?关于调整大小,对象可能会被重新排列,是的。考虑大小为4的<代码>表<代码>(最后索引为3,在基2中为11),索引14(1110)的散列。在这种情况下,该值将存储在索引
    3&14==11&1110==0011&1110==10==2
    处。随后,将
    表的大小调整为8(最后一个索引是7,或基数2中的111)。因此,当调整大小时,14将被索引为
    7&14==111&1110==0111&1110==110==6
    。因此,相同元素的
    数组中的索引在调整大小时从2变为6。至于您对
    get()
    方法的关注,节点不会“在彼此内部”索引。相反,您可以认为
    在每个索引处都有一个节点的链接列表,即使类型是
    Node[]
    。这是因为
    节点
    实例包含对
    下一个
    节点的引用。有关详细信息,请参见
    节点
    类的实现()。请注意,这称为链接。有关哈希表链接的描述,请参阅Wikipedia关于该主题的文章()。
    void resize(int newCapacity) {
         Entry[] oldTable = table;
         int oldCapacity = oldTable.length;
         if (oldCapacity == MAXIMUM_CAPACITY) {
             threshold = Integer.MAX_VALUE;
             return;
         }
         Entry[] newTable = new Entry[newCapacity];
         transfer(newTable);
         table = newTable;
         threshold = (int)(newCapacity * loadFactor);
     }