Java HashMap Source parsing 1

Source: Internet
Author: User

When explaining Hashmap<k,v>, let's take a look at how the API documentation describes it:

The implementation of a hash table-based MAP interface. This implementation provides all the optional mapping operations and allows NULL values and NULL keys to be used. (The HashMap class is roughly the same as Hashtable except for non-synchronous and null-allowed use.) This class does not guarantee the order of the mappings, especially because it does not guarantee that the order is constant.

This implementation assumes that the hash function distributes elements appropriately between buckets, providing stable performance for basic operations (get and put). The time required to iterate the collection view is proportional to the capacity of the HashMap instance (the number of buckets) and its size (number of key-value mappings). Therefore, if iteration performance is important, do not set the initial capacity too high (or set the load factor too low).

An instance of HashMap has two parameters that affect its performance: initial capacity and load factor. Capacity is the number of buckets in the hash table, and the initial capacity is just the capacity at the time of creation of the Hashtable. A load factor is a scale in which a hash table can reach a full amount before its capacity increases automatically. When the number of entries in the hash table exceeds the product of the load factor with the current capacity, the Hashtable is rehash (that is, rebuilding the internal data structure) so that the Hashtable will have about twice times the number of buckets.

Typically, the default load factor (. 75) seeks a tradeoff in time and space costs. The high load factor, while reducing the space overhead, also increases the query cost (which is reflected in the operations of most HASHMAP classes, including get and put operations). When setting the initial capacity, you should take into account the number of entries required in the mapping and their loading factors to minimize the number of rehash operations. The rehash operation does not occur if the initial capacity is greater than the maximum number of entries divided by the load factor.

If many of the mapping relationships are to be stored in the HASHMAP instance, creating it with a large enough initial capacity will make it more efficient to store the mapping relationship relative to the automatic rehash operation on demand to increase the capacity of the table.

Note that this implementation is not synchronous. if more than one thread accesses a hash map at the same time, and at least one of the threads modifies the mapping from the structure, it must remain externally synchronized. (Structural modification is any action that adds or deletes one or more mapping relationships; changing only the values associated with the key that the instance already contains are not structural modifications.) This is typically done by synchronizing the objects that naturally encapsulate the mapping. If such an object does not exist, you should use the Collections.synchronizedmap method to "wrap" the map. It is a good idea to do this at creation time to prevent unintended non-synchronous access to the mappings, as follows:

Map m =collections.synchronizedmap (new HashMap (...));

The iterator returned by all such "collection View Methods" is a quick failure: After the iterator has been created, if the mapping is modified from the structure, the iterator will throw unless modified by the Remove method of the iterator itself, any other time, in any way. Concurrentmodificationexception. Therefore, in the face of concurrent modifications, the iterator will soon fail completely without risking any uncertain behavior at any time in the future.

Note that the fast failure behavior of iterators is not guaranteed and, in general, there is no firm guarantee that there is an asynchronous concurrent modification. The fast-failing iterator does its best to throw concurrentmodificationexception. Therefore, it is wrong to write a program that relies on this exception, and the correct approach is that the fast failure behavior of the iterator should only be used to detect program errors.


Through the source we look at the HashMap constructor:

<strong>public HashMap () {        this.loadfactor = default_load_factor;        threshold = (int) (default_initial_capacity * default_load_factor);        Table = new Entry[default_initial_capacity];        Init ();} </strong>

Analysis:

This.loadfactor = Default_load_factor;

Here the loading factor is specified as default_load_factor,default_load_factor is defined in the source code:

Static final float default_load_factor = 0.75f;

Why the load factor is set to the 0.75,API document indicates that the default load factor (. 75) seeks a tradeoff in time and space costs. As for why this is said, I do not understand very well. Some of the online explanation is that when the loading factor is too large, the chance of conflict will increase, over the hour, will cause the waste of space, in the hash table, when we put a conflict, that is, two different objects, but their hashcode is the same, there appear occupy the same position in the table, Elements that conflict in the same location space are saved through a linked list, so when we get a conflict, we have to access the linked list, and frequent access to the linked list can be costly.


threshole= (int) (default_initial_capacity*default_load_factor);

We set the threshold value to Default_initial_capacity*default_load_factor

Value of default_initial_capacity:

static final int default_initial_capacity=16

That is, the threshold value is 12, which expands when the actual size exceeds this value.


Table = new Entry[default_initial_capacity];

An array of entities that store elements, that is, HashMap is a entry array, entry objects contain keys and values, let's take a look at entry:

Static Class Entry<k,v> implements Map.entry<k,v> {final K key;        V value;        Entry<k,v> Next;        final int hash;         /** * Creates new entry.            */Entry (int h, K K, v V, entry<k,v> N) {value = V;            Next = n;            key = k;        hash = h;        } Public final K GetKey () {return key;        Public final V GetValue () {return value;            Public final V SetValue (v newvalue) {v oldValue = value;            value = newvalue;        return oldValue; The public final Boolean equals (Object o) {if (!) (            o instanceof Map.entry)) return false;            Map.entry e = (map.entry) o;            Object K1 = GetKey ();            Object K2 = E.getkey (); if (k1 = = K2 | | (K1! = null && k1.equals (K2)))                {Object V1 = GetValue ();           Object v2 = E.getvalue ();     if (v1 = = V2 | |                    (V1! = null && v1.equals (v2)))            return true;        } return false; } public final int hashcode () {return (key==null? 0:key.hashcode ()) ^ (Value==nu ll?        0:value.hashcode ());        Public final String toString () {return GetKey () + "=" + GetValue (); }/** * This method is invoked whenever the value of a entry is * overwritten by an invocation of         Put (K,V) for a key k that's already * in the HASHMAP. */void Recordaccess (hashmap<k,v> m) {}/** * This method is invoked whenever the ENTR         Y is * removed from the table. */void Recordremoval (hashmap<k,v> m) {}}


Look at the entry constructor:


Entry (int h, K K, v V, entry<k,v> N) {            value = V;            Next = N;            key = k;            hash = h; }

where h represents the hash value, K for the key, V for the value, and N for the next node. From the above we also see that it implements Getkey (), GetValue (), SetValue (V value), Equals (Object O), hashcode () These functions,

See the implementation of the Equals method:


Public final Boolean equals (Object o) {            if (!) ( o instanceof map.entry))                return false;            Map.entry e = (map.entry) o;            Object K1 = GetKey ();            Object K2 = E.getkey ();            if (k1 = = K2 | | (K1! = null && k1.equals (K2))) {                Object v1 = GetValue ();                Object v2 = E.getvalue ();                if (v1 = = V2 | | (V1! = null && v1.equals (v2)))                    return true;            }            return false;        }


First judge whether it is an instance of Map.entry, not false, then take out their two key and value to judge, the same return true, otherwise return false.




Reprint Please specify source:http://blog.csdn.net/hai_qing_xu_kong/article/details/42176275 Emotional Control _




Java HashMap Source parsing 1

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.