HashMap源码 jdk1.8

慢慢来


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 当容量大于64所有长度大于8的bins都会会转为红黑树,小于8的还是单向链表
*/
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链表
  • 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
*/

 MIN_TREEIFY_CAPACITY 支持转为红黑树,数组(table)的最小长度 默认

/**
* The smallest table capacity for which bins may be treeified.
* (Otherwise the table is resized if too many nodes in a bin.)
* Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
* between resizing and treeification thresholds.
* 支持转为红黑树的容量的最小值为64,小于64不转为红黑树
*/
static final int MIN_TREEIFY_CAPACITY = 64;

int threshold;重组的数组个数阈值

/**
* The next size value at which to resize (capacity * load factor).
* 阈值 扩容的阈值 加载因子乘以容量
* @serial
*/
// (The javadoc description is true upon serialization.
// Additionally, if the table array has not been allocated, this
// field holds the initial array capacity, or zero signifying
// DEFAULT_INITIAL_CAPACITY.)
int threshold;

final float loadFactor;加载因子

/**
* The load factor for the hash table.
* 数组的加载因子
* @serial
*/
final float loadFactor;

 /* ---------------- Public operations -------------- */

 

 

  

 

posted @ 2021-01-06 17:22  wyzbky  阅读(86)  评论(0)    收藏  举报