码迷,mamicode.com
首页 > 其他好文 > 详细

HashMap源码 jdk1.8

时间:2021-01-08 10:57:21      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:pre   ref   xtend   float   ini   and   extends   max   treenode   

慢慢来


public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {}

tableSizeFor(int)

根据给定的容量大小,返回指定的int类型的数,这个数是2的次幂。看源码:

 /**
     * Returns a power of two size for the given target capacity.
     */
    static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

姿势:

  • 无符号右移 === 除以2的n次幂
    • public void run(){
              int n = 16;
              System.out.println(n>>>1);//除以2的1次方
              System.out.println(n<<1);//乘以2的1次方
              System.out.println(n>>>2);//除以2的2次方
          }
          /* 结果 */
          8
          32
          4
  • |=    对两边的数进行或运算遇一则一
    • let a = 5;      // 00000000000000000000000000000101
      a |= 3;         // 00000000000000000000000000000011
      
      console.log(a); // 00000000000000000000000000000111

 

姿势总结:

  源码中对给定的数进行除以2的1、2、4、8、16次幂的同时进行或等运算,这样就将给定数的二进制第一个1开始之后的所有位都补齐1。

  栗子:

    • /*
      32 的 二进制 100000
      补齐1 之后是 111111 
      返回63
      
      31 的 二进制 011111
      补齐1 之后是 011111
      返回31
      
      */

  给定数的对应2的次幂返回值。


 

 transient Node<K,V>[] table; 

姿势:

 transient /* 实现Serializable接口,使用transient关键字的属性不会被序列化 该变量内容在序列化后无法获得访问。*/ 

博客地址


 

属性

DEFAULT_INITIAL_CAPACITY 初始容量

 /**
     * The default initial capacity - MUST be a power of two.
     * 初始化的容量16,一定是2的倍数
     */
 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16       

MAXIMUM_CAPACITY 最大容量

/**
* The maximum capacity, used if a higher value is implicitly specified
* by either of the constructors with arguments.
* MUST be a power of two <= 1<<30.
* 最大容量等于2的30次方
*/
static final int MAXIMUM_CAPACITY = 1 << 30;

DEFAULT_LOAD_FACTOR 默认加载因子

/**
* The load factor used when none specified in constructor.
* 默认加载因子是0.75
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;

TREEIFY_THRESHOLD  转为红黑树的临界值

/**
* The bin count threshold for using a tree rather than list for a
* bin. Bins are converted to trees when adding an element to a
* bin with at least this many nodes. The value must be greater
* than 2 and should be at least 8 to mesh with assumptions in
* tree removal about conversion back to plain bins upon
* shrinkage.
* nodes长度大于8 bin 就会转为红黑树
*/
static final int TREEIFY_THRESHOLD = 8;

UNTREEIFY_THRESHOLD  从红黑树转化为链表的临界值

/**
* The bin count threshold for untreeifying a (split) bin during a
* resize operation. Should be less than TREEIFY_THRESHOLD, and at
* most 6 to mesh with shrinkage detection under removal.
* nodes长度等于6 bin 时变为链表
*/
static final int UNTREEIFY_THRESHOLD = 6;

姿势:

  • 链表的时间复杂度为 N/2
  • 红黑树的时间复杂度为 logN(以二为底)
  • 8/2 = 4  ,log8 = 3 ,8之后链表的时间复杂度程线性增长,而红黑树时间复杂度增长越来越慢。想想它们的图形。。
  • 这里nodes个数变为8转为红黑树,6又转会链表:这里面有时间和空间上的权衡。
  • 为啥不一直使用红黑树or链表

一直使用链表:当key离散性不好时,这个key的value会很长查询时间慢。在8之前时间复杂度都是差不多的。所以一直使用链表、而且8出现的概率在理想状态下非常低。个别bins中有红黑树对于这个key的查询效率有明显提升,相对整体hashmap的空间影响不大。

一直使用红黑树:红黑树的空间结构是链表的两倍,当nodes很少key很多时就会浪费空间。

  • 6转为链表应该是防止频繁转换。
     /* Because TreeNodes are about twice the size of regular nodes, we
     * use them only when bins contain enough nodes to warrant use
     * (see TREEIFY_THRESHOLD). And when they become too small (due to
     * removal or resizing) they are converted back to plain bins.  In
     * usages with well-distributed user hashCodes, tree bins are
     * rarely used.  Ideally, under random hashCodes, the frequency of
     * nodes in bins follows a Poisson distribution
     * (http://en.wikipedia.org/wiki/Poisson_distribution) with a
     * parameter of about 0.5 on average for the default resizing
     * threshold of 0.75, although with a large variance because of
     * resizing granularity. Ignoring variance, the expected
     * occurrences of list size k are (exp(-0.5) * pow(0.5, k) /
     * factorial(k)). The first values are:
     *
     * 0:    0.60653066
     * 1:    0.30326533
     * 2:    0.07581633
     * 3:    0.01263606
     * 4:    0.00157952
     * 5:    0.00015795
     * 6:    0.00001316
     * 7:    0.00000094
     * 8:    0.00000006
     * more: less than 1 in ten million
*/

 

 

  

 

HashMap源码 jdk1.8

标签:pre   ref   xtend   float   ini   and   extends   max   treenode   

原文地址:https://www.cnblogs.com/wyzbky/p/14242257.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!