欢迎光临散文网 会员登陆 & 注册

千锋教育Java入门全套视频教程(java核心技术,适合java零基础,Java

2023-07-22 21:34 作者:头痛  | 我要投稿

HashMap源码分析


transient Node<K,V>[] table;//HashMap的底层实现

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,

        boolean evict) {

  Node<K,V>[] tab; //临时数组   存放所有hash桶中的头节点

  Node<K,V> p; //临时节点 某一个桶的头节点(一个单向链表)

  int n, i;

  if ((tab = table) == null || (n = tab.length) == 0)//先赋值后判断

    n = (tab = resize()).length;//第一次初始化容量(16),之后为扩容

  if ((p = tab[i = (n - 1) & hash]) == null)

    //取hash后log n 位决定数值放在哪个位置

    //为了防止漏桶,n(容量)必须为2的多次方

    //无参,默认为16,扩容是翻倍

    //带参时,通过tableSizeFor方法获取设定容量最接近的大于容量的2的多次方,扩容是翻倍

    tab[i] = newNode(hash, key, value, null);//如果这个桶里一个元素都没有,则直接放入元素

  else {

    //指向的hash桶里有东西时

    Node<K,V> e; 

    K k;

    if (p.hash == hash &&//如果加入的key与第一个是一样的

      ((k = p.key) == key || (key != null && key.equals(k))))

      e = p;//用e暂存相同的节点

    else if (p instanceof TreeNode)//如果头结点是一个树节点

      e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);

    //调用红黑树的方法往树里添加节点,如果没有重复,返回null

    //如果有返回这个节点并用e暂存 

    else {//如果是链表

      for (int binCount = 0; ; ++binCount) {

        if ((e = p.next) == null) {//判断p的下一节点是否为空

          p.next = newNode(hash, key, value, null);//如为空,将数值放到此位置

          if (binCount >= TREEIFY_THRESHOLD - 1) // 是否树化

            treeifyBin(tab, hash);

          break;

        }

        if (e.hash == hash &&//找到相同节点

          ((k = e.key) == key || (key != null && key.equals(k))))

          break;

        p = e;

      }

    }

    if (e != null) { // 有相同节点时返回被覆盖的值

      V oldValue = e.value;

      if (!onlyIfAbsent || oldValue == null)

        e.value = value;

      afterNodeAccess(e);

      return oldValue;

    }

  }

  ++modCount;

  if (++size > threshold)//到达阈值后扩容

    resize();

  afterNodeInsertion(evict);

  return null;

}

千锋教育Java入门全套视频教程(java核心技术,适合java零基础,Java的评论 (共 条)

分享到微博请遵守国家法律