Java 关于HashMap内部实现的查询

Java 关于HashMap内部实现的查询,java,hashmap,hashtable,Java,Hashmap,Hashtable,我将介绍HashMap的实现,并参考以下链接: 我发现“HashMap包含一个bucket数组,以便包含其条目”。所以,我有几个问题- 桶数组的类型是什么 既然数组有缺点(例如,固定大小和只允许同质数据),那么尽管存在这些缺点,我们为什么要使用数组呢 3.如果键或冲突的哈希代码相同,则使用链表。如何获取(搜索)第二、第三个节点的引用等 谢谢你 桶数组的类型是什么 这取决于你制作的映射,如果你制作了一个HashMap,那么bucket将是那些类型的,能够包含那些类型的对象 既然数组有缺点(例如,固

我将介绍HashMap的实现,并参考以下链接: 我发现“HashMap包含一个bucket数组,以便包含其条目”。所以,我有几个问题-

  • 桶数组的类型是什么
  • 既然数组有缺点(例如,固定大小和只允许同质数据),那么尽管存在这些缺点,我们为什么要使用数组呢
  • 3.如果键或冲突的哈希代码相同,则使用链表。如何获取(搜索)第二、第三个节点的引用等

    谢谢你

  • 桶数组的类型是什么
  • 这取决于你制作的映射,如果你制作了一个
    HashMap
    ,那么bucket将是那些类型的,能够包含那些类型的对象

  • 既然数组有缺点(例如,固定大小和只允许同质数据),那么尽管存在这些缺点,我们为什么要使用数组呢
  • 因为与性能增益相比,缺点是值得的。因为数组的大小是固定的,所以可以跳过很多检查(例如,是否存在此索引?)。 你可以在这里读到更多关于这方面的内容;及

  • 如果键或冲突使用相同的哈希代码,它将使用链表。它如何获取(搜索)第二、第三个节点的引用等
  • 这在这里比我能解释得更好

  • 桶数组的类型是什么
  • 这取决于你制作的映射,如果你制作了一个
    HashMap
    ,那么bucket将是那些类型的,能够包含那些类型的对象

  • 既然数组有缺点(例如,固定大小和只允许同质数据),那么尽管存在这些缺点,我们为什么要使用数组呢
  • 因为与性能增益相比,缺点是值得的。因为数组的大小是固定的,所以可以跳过很多检查(例如,是否存在此索引?)。 你可以在这里读到更多关于这方面的内容;及

  • 如果键或冲突使用相同的哈希代码,它将使用链表。它如何获取(搜索)第二、第三个节点的引用等
  • 这在这里比我能解释得更好

  • 它是一个内部对象,包含键、值和对bucket中下一个节点的引用(以实现单个链表)
  • 阵列需要2次方的固定大小。给定键的数组的索引基于键的哈希代码的逻辑AND(&)和数组的大小,数组的大小是哈希表的实际“魔力”
  • bucket中的链表用于处理哈希代码冲突。这就是HashMap.get()的最坏情况复杂性为O(n)的原因-如果所有键都具有相同的哈希代码,并且搜索的键是bucket中的最后一个键,则会发生这种情况 如果hashmaps增长,则会有一个非常昂贵的重设函数,因为数组也必须增长到下一个2的幂。在这种情况下,每个桶都必须重新计算其索引。在这种情况下,将构造一个新数组。这意味着不需要动态数据结构

    如果使用合适的容量参数创建新的hashmap,则可以避免重新灰烬

  • 它是一个内部对象,包含键、值和对bucket中下一个节点的引用(以实现单个链表)
  • 阵列需要2次方的固定大小。给定键的数组的索引基于键的哈希代码的逻辑AND(&)和数组的大小,数组的大小是哈希表的实际“魔力”
  • bucket中的链表用于处理哈希代码冲突。这就是HashMap.get()的最坏情况复杂性为O(n)的原因-如果所有键都具有相同的哈希代码,并且搜索的键是bucket中的最后一个键,则会发生这种情况 如果hashmaps增长,则会有一个非常昂贵的重设函数,因为数组也必须增长到下一个2的幂。在这种情况下,每个桶都必须重新计算其索引。在这种情况下,将构造一个新数组。这意味着不需要动态数据结构

    如果使用合适的容量参数创建新的hashmap,则可以避免重新灰烬。

    来自:

  • 这些容器可以是列表,也可以是树,具体取决于它们所包含的元素数量
  • 在这种情况下,阵列的同质性不是问题,访问速度超过了调整阵列大小的成本
  • HashMap始终使用相同的哈希对所有值进行迭代,测试它们是否具有正确的键:
  • final节点getNode(int散列,对象键){
    节点[]选项卡;节点第一,e;int n;K;
    如果((tab=table)!=null&(n=tab.length)>0&&
    (first=tab[(n-1)&散列]!=null){
    如果(first.hash==hash&&//始终检查第一个节点
    ((k=first.key)==key | |(key!=null&&key.equals(k)))
    先返回;
    if((e=first.next)!=null){
    if(树节点的第一个实例)
    return((TreeNode)first).getTreeNode(hash,key);
    做{
    如果(e.hash==hash&&
    ((k=e.key)==key | |(key!=null&&key.equals(k)))
    返回e;
    }而((e=e.next)!=null);
    }
    }
    返回null;
    }
    
    来自:

  • 这些容器可以是列表,也可以是树,具体取决于它们所包含的元素数量
  • 在这种情况下,阵列的同质性不是问题,访问速度超过了调整阵列大小的成本
  • HashMap始终使用相同的哈希对所有值进行迭代,测试它们是否具有正确的键:
  • final节点getNode(int散列,对象键){
    节点[]选项卡;节点第一,e;int n;K;
    如果((tab=table)!=null&(n=tab.length)>0&&
    (first=tab[(n-1)&散列]!=null){
    如果(first.hash==hash&&//始终检查第一个节点
    ((k=first.key)==key | |(key!=null&&key.equals(k)))
    先返回;
    if((e=first.next)!=null){
    if(fir)
    
    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;
    
    }