简体   繁体   English

查询HashMap的内部实现

[英]Query about internal implementation of HashMap

I am going through HashMap implementation and referring to this link: How does Java implement hash tables? 我正在研究HashMap的实现,并引用此链接: Java如何实现哈希表? I am finding that "A HashMap contains an array of buckets in order to contain its entries". 我发现“ HashMap包含一组存储桶以便包含其条目”。 So, I have few questions- 所以,我有几个问题-

  1. What is the type of the array of buckets. 值区阵列的类型是什么。
  2. Since array has drawbacks (eg fixed size and allowed only homogeneous data).Then why we are using arrays despite of these drawbacks. 由于数组具有缺点(例如,固定大小且仅允许同类数据)。因此,尽管有这些缺点,我们为什么仍使用数组。

3.In case of same hashcode for a key or collision it uses linked list.How it gets(search) the reference of the second, third node etc. 3,如果键或冲突的哈希码相同,则使用链表,它如何获取(搜索)第二,第三节点的引用等。

Thanks in adv. 感谢在广告中。

  1. What is the type of the array of buckets. 值区阵列的类型是什么。

That depends on the map you make, if you make a HashMap<Integer, String> then the buckets will be of those types, able to contain those types of objects 这取决于您创建的地图,如果您创建了HashMap<Integer, String>则存储桶将属于这些类型,并且能够包含那些类型的对象

  1. Since array has drawbacks (eg fixed size and allowed only homogeneous data).Then why we are using arrays despite of these drawbacks. 由于数组具有缺点(例如,固定大小且仅允许同类数据)。因此,尽管有这些缺点,我们为什么仍使用数组。

Because the drawbacks are worth it compared to the performance gain. 与性能提升相比,缺点是值得的。 Because arrays are a fixed size, a lot of checks can be skipped (ie does this index exist?). 由于数组是固定大小的,因此可以跳过很多检查(即,该索引是否存在?)。 You can read more about that here; 您可以在此处了解更多信息。 https://en.wikiversity.org/wiki/Java_Collections_Overview and Why not always use ArrayLists in Java, instead of plain ol' arrays? https://en.wikiversity.org/wiki/Java_Collections_Overview为什么不总是在Java中使用ArrayList而不是普通的ol'数组?

  1. In case of same hashcode for a key or collision it uses linked list.How it gets(search) the reference of the second, third node etc. 如果键或冲突的哈希码相同,则使用链表,它如何获取(搜索)第二,第三节点的引用等。

That is explained here better than I can; 这比我能解释的更好。 What happens when a duplicate key is put into a HashMap? 将重复的密钥放入HashMap后会发生什么?

  1. It's an internal Object which contains the key, value and a reference to the next node in the bucket (to realize a single linked list) 它是一个内部对象,其中包含键,值和对存储桶中下一个节点的引用(以实现单个链接列表)
  2. A fixed size of a power of 2 is needed for the array. 该阵列需要2的幂的固定大小。 The index of the array for a given key is based on a logical AND (&) of the hashcode of the key and the size of the array which is the actual "magic" of a hash table. 给定键的数组索引基于键的哈希码的逻辑与(&)和作为哈希表实际“魔术”的数组大小。
  3. The linked list in a bucket is needed to deal with hashcode collisions. 存储桶中的链表是处理哈希码冲突所必需的。 This is the reason for the worst case complexity of O(n) of HashMap.get() - happens if all keys have the same hashcode and the searched key is the last one in the bucket. 这是HashMap.get()的O(n)最坏情况下的复杂性的原因-如果所有键都具有相同的哈希码并且搜索到的键是存储桶中的最后一个键,则会发生这种情况。

If the hashmaps grows there is a very expensive rehash function, because the array has to grow to the next power of 2 aswell. 如果哈希图增加,那么将有一个非常昂贵的重新哈希函数,因为数组也必须增长到下一个2的幂。 In this case every bucket has to recalulate its index. 在这种情况下,每个存储桶都必须重新计算其索引。 In this case a new array is constructed. 在这种情况下,将构建一个新的数组。 This means there is no dynamic data structure needed. 这意味着不需要动态数据结构。

You can avoid rehashes if you create a new hashmap with a suitable capacity argument. 如果使用适当的容量参数创建新的哈希表,则可以避免重新哈希。

From the OpenJDK8 code source : OpenJDK8代码源

  1. The bins are either Lists or Trees, depending on the amount of elements they hold 垃圾箱可以是列表,也可以是树,具体取决于它们所容纳的元素数量
  2. The homogeneity of arrays isn't a problem in this context, and access speed primes over the cost of resizing the array 在这种情况下,数组的同质性不是问题,并且访问速度优先于调整数组大小的成本
  3. The HashMap always iterate over all the values with a same hash, testing whether they have the correct key : HashMap始终迭代具有相同哈希值的所有值,以测试它们是否具有正确的键:
final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        if (first.hash == hash && // always check first node
            ((k = first.key) == key || (key != null && key.equals(k))))
            return first;
        if ((e = first.next) != null) {
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key);
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM