"Explore SRC" together to see HashMap source code

Source: Internet
Author: User
Tags rehash

HashMap source code has been a lot of Java Programmer's Way, today I also see, we join in the fun? Based on the limited level, some places understand the mistake, can not understand, please point out oh ~ ~

> Release Notes

The version viewed is jdk1.7.0_71

> Structure Outline Diagram

> Look at the construction method.
 Public HASHMAP (intfloat  loadfactor) public HashMap (int  initialcapacity)   public HashMap ()publicextendsextends v> m)

HashMap has 4 construction methods, the specific look at the code, that the 2nd, 3 methods are called the 1th method to operate. Well, look at the 1th one.

Static Final int // aka Static Final float Default_load_factor = 0.75f;

Look at the global variables of the parameters, knowing that the initialization capacity is 16, and the expansion factor (the container where the capacity reaches when the HashMap is to be reconstructed) defaults to 0.75.

Finally, the 1th method of the method body, mainly made 3 things:

1, if the import parameter exception, throw an exception

2, the initial capacity to fill the top

3, set the entry parameter as a property, here is a little note: Threshold (threshold), in HashMap just initialized the city is assigned to the initial capacity.

4, later, also called the Init () for the sub-class developer extension? (guessed)

> Which methods are used, of course, is the method of the bullet--put (K key, V value)
if(Table = =empty_table) {inflatetable (threshold);}
......
/*** inflates the table.*/Private voidInflatetable (inttosize) { //Find a power of 2 >= tosize intCapacity =roundUpToPowerOf2 (tosize); Threshold= (int) Math.min (capacity * Loadfactor, maximum_capacity + 1); Table=NewEntry[capacity]; Inithashseedasneeded (capacity);}

Inside there is an array called table whose elements are pointing to the linked list, and this list is loaded with elements that actually contain key and value.

When the HashMap is initialized, the table is empty at this point, and the table needs to be scaled up according to Threshold .

Expands the table to the n-th size of the threshold with 2. For example,threshold is 16, then expands to17 and threshold to 32.

Note:

ROUNDUPTOPOWEROF2 () see below.

if NULL )    return  putfornullkey (value);

View the Putfornullkey method, put the key null element, into the table below the list of tables 0. The logic is basically consistent with the logic to put the elements below.

Note:

Why is the element with the subscript 0 put the value of the key null? See below.

int hash = hash (key); int i = indexfor (hash, table.length);

When the key object is hashed, it is mapped to a position in the table array, which is I.

Note:

Indexfor (), see below.

 for null; E = e.next) {    Object k;     if (E.hash = = Hash && (k = e.key) = = Key | | Key.equals (k))) {        = e.value;         = value;        E.recordaccess (this);         return oldValue;}    }

The above has found where the currently inserted element is located in the table array, then linearly traverse the linked list to which the position points, if the hash value is found to be equal and key is equal, the map already contains this element, then overwrite the old value with the new value and return the old value.

modcount++; AddEntry (hash, key, value, I);/*** Adds A new entry with the specified key, value and hash code to * the specified bucket. It is the responsibility of this * method to resize the table if appropriate. * * Subclass overrides this to alter the behavior of put method. */voidAddEntry (intHash, K key, V value,intBucketindex) {    if(Size >= threshold) && (NULL!=Table[bucketindex])) {Resize (2 *table.length); Hash= (NULL! = key)? Hash (key): 0; Bucketindex=indexfor (hash, table.length); } createentry (hash, key, value, Bucketindex);}/*** like AddEntry except, this version was used when creating entries * as part of MAP construction or "Pseudo-const  Ruction "(cloning, * deserialization). This version of Needn ' t worry about resizing the table. * * Subclass overrides this to alter the behavior of HASHMAP (MAP), * clone, and ReadObject. */voidCreateentry (intHash, K key, V value,intBucketindex) {Entry<K,V> e =Table[bucketindex]; Table[bucketindex]=NewEntry<>(hash, key, value, E); Size++;}

The program runs here, indicating that the key value is not found in the map and needs to be inserted.

Modcount is the number of times a record is inserted and is estimated to be used to limit concurrent operations.

AddEntry () before inserting the element, to determine whether the element reached a threshold, if so, the table is twice times the capacity to expand, re-hash. (this point is described below)

Then, recalculate the position of the element after the expansion, call Createentry () for the actual insert operation. The Insert action is to point to the first element of the linked list with next to the newly inserted element, and then point the table number to the new inserted element.

/*** Rehashes The contents of this map to a new array with a * larger capacity. This method was called automatically when the * number of the keys on this map reaches its threshold. * * If current capacity are maximum_capacity, this method does not * Resize the map, but sets threshold to Integer.max_valu E. * This have the effect of preventing future calls. * * @paramnewcapacity The new capacity, must be a power of both; * must be greater than current capacity unless current * Capacity is maximum_capacity (in which case value * is irrelevant). */voidResizeintnewcapacity) {entry[] oldtable=table; intOldcapacity =oldtable.length; if(Oldcapacity = =maximum_capacity) {Threshold=Integer.max_value; return; } entry[] NewTable=NewEntry[newcapacity];    Transfer (newtable, inithashseedasneeded (newcapacity)); Table=newtable; Threshold= (int) math.min (newcapacity * loadfactor, maximum_capacity + 1);}/*** Transfers all entries from the current table to newtable.*/voidTransfer (entry[] newtable,Booleanrehash) {    intNewcapacity =newtable.length;  for(entry<k,v>e:table) {         while(NULL!=e) {Entry<K,V> next =E.next; if(Rehash) {E.hash=NULL= = E.key? 0: Hash (E.key); }            inti =indexfor (E.hash, newcapacity); E.next=Newtable[i]; Newtable[i]=e; E=Next; }    }}

First, instantiate a new table based on newcapacity .

Because the length of the new table changes, you need to traverse all the elements of the linked list pointed to by the original table, and go to the new table (calculate hash, reposition). (as to whether to re-hash, I have not read it)

> Details > roundUpToPowerOf2 (int number)
Private Static int roundUpToPowerOf2 (int number ) {    //  assert number >= 0: "Number must B e non-negative ";    return number >= maximum_capacity            ?  Maximum_capacity            > 1)? Integer.highestonebit ((number-1) << 1): 1;}

This method calculates the nth number of the nearest 2.

where Integer.highestonebit () is the highest bit 1 corresponding to the number, if it is positive, return is the closest to its small 2 of the n-th square, if it is negative, the return is 2147483648, that is, the minimum value of the integer.

Then why do you want to lose 1 and then ask for Highestonebit ()?

A few numbers of binaries will tell you:

00001111 = 00011110 = Highestonebit (30) = 16

00010000 = 00100000 = Highestonebit (32) = 32

So, to get the nth number of the nearest 2, subtract one first.

A simple decomposition calculation is attached:

 public  class   Lefter { static  void   main (string[] args) {for  (int  i = 2; I <=; I++) {SYSTEM.OUT.PRINTLN (i);            SYSTEM.OUT.PRINTLN (i -1);            System.out.println ((i -1) << 1);            System.out.println (Integer.highestonebit ((I -1) << 1 "Result:" + i + "-" + integer.highestonebit (i-1) << 1)); }    }}
View Code

Results:

2122Result:2-23244Result:3-44364Result:4-45488Result:5-865108Result:6-876128Result:7-887148Result:8-8981616Result:9-161091816Result:1611102016Result:1612112216Result:1613122416Result:1614132616Result:1615142816,Result:1616153016Result:1617163232Result:32
View Code

> indexfor (int h, int length)

The h is mapped to the range of length, and the effect is like a modulo.

return H & (length-1);

Put H and length-1 and operate on it.

For example, length is 16, then:

16 = 00010000

15 = 00001111

> Why is the element with the subscript 0 put the value of the key null?

According to the above indexfor (int h, int length) mapping the range is 1 to length-1, then the remaining subscript is 0.

> Why is the length of the hash array to be 2 of the n-th square?

I think this is for the sake of & arithmetic (because of the high efficiency of the & operation), and with the & operation there is a limit, that is, 2 of the N-time in the side, so. (Personal understanding, I do not know whether or not)

> The rest is still not clear

1, inithashseedasneeded (capacity)

2, hash ()

"Explore SRC" together to see HashMap source code

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.