"Schematic JDK source" hashmap capacity-size growth principle (jdk1.6/1.7/1.8)

Source: Internet
Author: User

1. Preface

The capacity of the HashMap is automatically expanded based on how much of the data is stored, that is, when the number of HashMap stored data reaches a threshold (threshold), then adding data to it may expand the capacity of HashMap.

possible?

In fact, due to the different JDK versions, the default size of their thresholds (threshold) also becomes different (mainly the change of the calculation formula), even the judging condition becomes dissimilar, so if said threshold = capacity * Loadfactor (capacity * Load factor) will no longer be absolutely correct, even more than the threshold capacity will grow and no longer absolutely correct, the following is JDK1.6, 1.7, 1.8 in the source code description.

Note: This article is not pictured, the title is only to match the previous text title

2. JDK 1.6

The source code for the HashMap constructor in JDK 1.6 is as follows (with Mark opening comments and Chinese comments, non-JDK source comments, hereinafter):

 Public HashMap(intInitialcapacity,floatLoadfactor) {//Mark A Begin    if(Initialcapacity <0)Throw NewIllegalArgumentException ("Illegal initial capacity:"+ initialcapacity);if(Initialcapacity > maximum_capacity) initialcapacity = maximum_capacity;if(Loadfactor <=0|| Float.isnan (Loadfactor))Throw NewIllegalArgumentException ("Illegal load factor:"+ Loadfactor);//Find a power of 2 >= initialcapacity    intCapacity =1; while(Capacity < initialcapacity) capacity <<=1;//Mark A End     This. loadfactor = Loadfactor; Threshold = (int) (capacity * loadfactor);//Calculate thresholds, focus on this codeTable =NewEntry[capacity]; Init ();}

Where code snippet A (Mark a begin-mark a End, same as) can be ignored first, the main is

threshold = (int)(capacity * loadFactor);

Here is the formula for the threshold, where the default value of capacity (capacity) is 16,loadfactor (load factor), the default value is 0.75, then

threshold = (int)(16 * 0.75) = 12

Look again at the AddEntry function (the put (K, V) method finally inserts the data through this function, see "Schematic JDK source code" HashMap the rationale and its thread security):

void addEntry(intint bucketIndex) {    Entry<K,V> e = table[bucketIndex];    new Entry<K,V>(hash, key, value, e);    if (size++ >= threshold)  // 判断是否扩充容量        resize(2 * table.length);}

You can see that as long as the current quantity is greater than or equal to the threshold, the capacity of the hashmap is twice times its current capacity. This is the feature under JDK 1.6.

3. JDK 1.7

The source code of the HashMap constructor in JDK1.7 is as follows:

 Public HashMap(intInitialcapacity,floatLoadfactor) {//Mark A Begin    if(Initialcapacity <0)Throw NewIllegalArgumentException ("Illegal initial capacity:"+ initialcapacity);if(Initialcapacity > maximum_capacity) initialcapacity = maximum_capacity;if(Loadfactor <=0|| Float.isnan (Loadfactor))Throw NewIllegalArgumentException ("Illegal load factor:"+ Loadfactor);//Mark A End     This. loadfactor = Loadfactor; threshold = initialcapacity;//Calculate thresholds, focus on this codeInit ();}

Similarly, the code snippet a can be ignored, then the above code, you can see that the calculation of the threshold is completely different from JDK 1.6, it is independent of the contract factor, but directly using the initial size as the threshold size, but this is only for the first change in size before Because in the Resize function (a function that alters the size of a capacity, which is called this function), there is the following code:

threshold = (int)Math.min1);

That is, after changing the size, the value of threshold is still related to the load factor, which is similar to that in JDK 1.6 (when the capacity reaches the maximum value of 1,073,741,824 is not discussed).

And the AddEntry function is also different from JDK 1.6, the source code is as follows:

void addEntry(intint bucketIndex) {    if ((size >= threshold) && (null// 判断语句发生了改变        resize(2 * table.length);        hash = (null0;        bucketIndex = indexFor(hash, table.length);    }    createEntry(hash, key, value, bucketIndex);}

As can be seen from the above code, in JDK 1.6, determine whether the expansion size is directly determine whether the current quantity is greater than or equal to the threshold, and JDK 1.7 can be seen, it is judged whether to expand the size in addition to determine whether the current quantity is greater than or equal to the threshold value, It is also necessary to ensure that the current data to be inserted in the bucket cannot be empty (the details of the bucket can be found in the "schematic JDK source" HashMap basic principle and its thread safety). So what about JDK 1.8?

3. JDK 1.8

Description: JDK 1.8 For the implementation of the HashMap, the new red-black tree features, so its underlying implementation principle has become different, no longer discussed.

The source code for the HashMap constructor in JDK 1.8 is as follows:

 Public HashMap(intInitialcapacity,floatLoadfactor) {//Mark A Begin    if(Initialcapacity <0)Throw NewIllegalArgumentException ("Illegal initial capacity:"+ initialcapacity);if(Initialcapacity > maximum_capacity) initialcapacity = maximum_capacity;if(Loadfactor <=0|| Float.isnan (Loadfactor))Throw NewIllegalArgumentException ("Illegal load factor:"+ Loadfactor);//Mark A End     This. loadfactor = Loadfactor; This. Threshold = Tablesizefor (initialcapacity);//Calculate threshold value}

Here the Tablesizefor method is used, the source code is as follows:

staticfinalint tableSizeFor(int cap) {    int1;    1;    2;    4;    8;    16;    return011;}

Because the bit operation is used, the method can not know the result clearly, but as long as it knows no matter what value is entered, its final result will be 0,1,2,4,8,16,32,68 ... One of these numbers is right (in fact, it's regular), for the following input values:

tablesizefor(+)= 16tablesizefor(+)= 32tablesizefor($)= 64tablesizefor(+)= 64tablesizefor(+)= 128tablesizefor(+)= 128tablesizefor(a)= 128tablesizefor(+)= 128tablesizefor(144)= 256

That is to say, for the initial value of the capacity 16来 said that its initial threshold is 16, and JDK 1.7 is the same as the initial threshold, and its resize function, threshold calculation source as follows:

FinalNode<k,v>[] Resize () {node<k,v>[] oldtab = table;intOldcap = (Oldtab = =NULL) ?0: Oldtab.length;intOldthr = threshold;intNewcap, Newthr =0;if(Oldcap >0) {if(Oldcap >= maximum_capacity) {threshold = Integer.max_value;returnOldtab; }Else if(Newcap = Oldcap <<1) < maximum_capacity && Oldcap >= default_initial_capacity) newthr = Oldthr <& Lt1;//Double threshold}Else if(Oldthr >0)//Initial capacity was placed in thresholdNewcap = Oldthr;Else{//Zero initial threshold signifies using defaultsNewcap = default_initial_capacity; Newthr = (int) (Default_load_factor * default_initial_capacity); }if(Newthr = =0) {floatFT = (float) Newcap * Loadfactor;//load factor hereNewthr = (Newcap < maximum_capacity && ft < (float) maximum_capacity? (int) Ft:Integer.MAX_VALUE); } threshold = Newthr;//code too much, omit the following code}

The calculation becomes more complex because its underlying implementation principle is not just as simple as the array Galin in the previous JDK, but it is still possible to see that the calculation of its threshold is related to the load factor.

and its judgment whether to expand the statement in the Putval function (Put method will call), the source code is as follows:

final V putVal(intbooleanboolean evict) {    // 代码太多,省略    ++modCount;    if// 判断是否扩充语句        resize();    afterNodeInsertion(evict);    returnnull;}

It can be seen that the threshold value is the same as JDK 1.6, and does not determine whether the bucket is not empty as in JDK 1.7.

Summarize

JDK 1.6 capacity is expanded when the number is greater than the capacity * load factor.

The JDK 1.7 was first expanded to: when the quantity is larger than the capacity, the second and later: expands when the quantity is greater than the capacity * load factor.

JDK 1.8 was first expanded to be: independent of load factor, second and later: related to load factor. The detailed calculation process needs to be explained in detail.

Note: the above is not considered when the maximum capacity of the situation.

Schematic JDK source HashMap capacity growth principle (jdk1.6/1.7/1.8)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.