A brief analysis of Java map source code

Source: Internet
Author: User
Tags concurrentmodificationexception

Map is a key-value pair. is also a frequently used data structure.

The map interface defines the basic behavior of the MAP. The method that contains the most core get and put operations, defined by this interface, is as Follows:


There are different map implementations in the jdk, which are suitable for different application scenarios. such as Thread-safe Hashtable and Non-thread-safe hashmap.

For example, the UML class diagram is a subclass of the map interface in the jdk, and there is a special case dictionary is not recommended for use:


The methods we need to focus on in the map interface are get, put, and iterator-related methods such as EntrySet (), KeySet (), and the values () method.

Entry

Before you start analyzing the map, first understand the storage of the elements in the MAP. We know that map can think of as a set of Key-value pairs, and in java, Map uses entry to store Key-value pairs, which is an interface whose definition is simple and straightforward. The interface method mainly operates on keys and Values.

Interface entry<k,v> {       K getKey ();     V GetValue ();    V setValue (v value);     Boolean equals (Object o);     int hashcode ();    }

Abstractmap

The abstract implementation of the map Interface. See the following demo sample implementation code:

Map<string,string> a =/** * * abstract Map Implementation schematic, According to the document SAID.        and the list interface and its Similarity. * *map is divided into two types: variable and immutable.        Immutable only needs to implement the EntrySet method, and the returned set iterator cannot support the change Operation. * * variable map, the need to implement the put method, and then EntrySet iterator also need to support the change operation * * *abstractmap inside the map to achieve the outline, but its efficiency is difficult to say, for example, its get method used by the party Law Entryset.

* * Usually subclasses are covered in a more efficient way.

such as hashmap, keyset, values, get method, etc. */new abstractmap<string,string> () {/* * return MA The collection of elements in p, the returned collection usually inherits Abstractset. */@Override public set<map.entry<string, string>> entryset () {return New Ab stractset<map.entry<string,string>> () {@Override Public iterator<java.u Til. map.entry<string, string>> iterator () {return null; } @Override public int size () {return 0; } }; }/* * The default implementation throws an exception, the variable map needs to implement this method */@Override public String put ( String key, string Value) {return null; } };

HashMap

HashMap inherits abstractmap, which is quite often used in the data structure, with the idea of hashing Hash. Ability to insert and fetch data within the time complexity of O (1). Its basic implementation can analyze the abstract methods in the previous section, the article

Analysis of the implementation and performance of HashMap the implementation of hashmap, put and get operations are described in more Detail.

Don't repeat it here. The key is to see his iterator implementation, where only the next EntrySet () method is analyzed, while the keyset () and the values () method are implemented in a vein.

About Iterators. See the following excerpt from the source code and related gaze:

/** * Returns a collection of all key-value pairs in the Map, used to traverse */public set<map.entry<k,v>> entryset () {return Entry        Set0 ();         }/** * Deferred initialization, built only when Used.            * * The values () and KeySet () methods also use a similar mechanism */private set<map.entry<k,v>> entrySet0 () {            set<map.entry<k,v>> es = entryset; return es! = null?        Es: (entryset = new EntrySet ());         }/** * True Enteryset is an internal class whose key implementation is an iterator Implementation.         * * The values () and KeySet () methods also correspond to the corresponding inner Classes. * Corresponding to the implementation of their own iterators.            The key is this iterator * */private final class EntrySet extends Abstractset<map.entry<k,v>> {            Public iterator<map.entry<k,v>> Iterator () {return newentryiterator (); } public boolean contains (Object o) {if (!) (                o instanceof map.entry)) return false; Map.entry<k,v> e = (map.entry<k,V>) o;                entry<k,v> candidate = Getentry (e.getkey ());            return candidate! = null && candidate.equals (e);            The public boolean remove (Object o) {return removemapping (o) = null;            } public int size () {return size;            } public void Clear () {HashMap.this.clear ();         }}/** * EntrySet iterator, inherits hashiterator, implements next Method. * The values () and KeySet () methods are also inherited Hashiterator.         The only way to implement next is Different.         * * Can be controlled under. * * Key is hashiterator * * */private final class Entryiterator extends hashiterator& Lt            Map.entry<k,v>> {public map.entry<k,v> Next () {return nextentry (); }}/** * *keyset () corresponding iterator */private final class Keyiterator extends H       ashiterator<k> {     Public K next () {return nextentry (). getKey (); }}/** * * HashMap entryset () keySet () Universal iterator for values () */priva   TE Abstract class Hashiterator<e> implements Iterator<e> {entry<k,v> next; Next entry to return int expectedmodcount;     for Fast-fail int index;   Current Slots entry<k,v> current;                Current entry Hashiterator () {expectedmodcount = modcount;                    If (size > 0) {//advance to first entry entry[] t = table; At the time of construction, find the first non-nullable array element in the array, namely the entry linked list, see//i am in front of the blog while (index < T.le                Ngth && (next = T[index++]) = = null);            }} Public Final Boolean hasnext () {return next! = null; }             /**             * Key implementation, very easy to Read. When looking for next, the same as when constructing the iterator */final entry<k,v> nextentry () {if (modcount! = expect                Edmodcount) throw new Concurrentmodificationexception ();                Entry<k,v> e = next;                 if (e = = Null) throw new Nosuchelementexception ();                    If (next = E.next) = = Null) {entry[] t = table;                While (index < t.length && (next = T[index++]) = = null);                } current = e;            Return e; } public void Remove () {if (current = = Null) throw new Illegalstateexceptio                N ();                If (modcount! = Expectedmodcount) throw new Concurrentmodificationexception ();                Object k = current.key;                Current = null;               HashMap.this.removeEntryForKey (k); Expectedmodcount = modcount; }         }

HashTable

The implementation is basically consistent with hashmap, just adding synchronous operations to the METHOD.

It can be used in a multithreaded Environment. But now there is concurrenthashmap, in high concurrency, can be used to replace the Hashtable.

Linkedhashmap

HashMap may not meet the requirements in some scenarios, because the elements put into them are unordered. and Linkedhashmap to some extent to solve the Problem.

It inherits the HashMap on the implementation, expands the Haspmap.enteyset on the storage, and adds the before, after FIELDS. The elements of the HashMap are connected by a doubly linked List. This doubly linked list determines the order in which it is Traversed.

The order is usually inserted in the order of the map, but it has a field accessorder when true, the traversal order will be the LRU Effect.

Study the Order of it. We can start with the put method, the get method, and the traversal method. First look at the get method:

/**         * Calls the Getentry method of the parent class Directly.

The key is * e.recordaccess (THIS) Code * * * Public V get (Object key) { entry<k,v> e = (entry<k,v >) getentry (key); if (e = = Null) return null; E.recordaccess (this); return e.value; } /** * Entry.recordaccess Method * * The assumption is the order of access (accessorder=true), then put it in the next position of the head node * Otherwise do nothing. * This allows you to determine the order of traversal based on the initial accessorder Property. */ void recordaccess (hashmap<k,v> m) { linkedhashmap<k,v> lm = (linkedhashmap<k,v> ) m; If (lm.accessorder) { lm.modcount++; Remove (); Addbefore (lm.header); } }



Put Method:

the/** * Put method calls this method, overriding the implementation in the parent class, */void addentry (int hash,k key, V value, int Bucketindex) {             Createentry (hash, key, value, bucketindex);             Remove eldest entry if instructed, else grow capacity if appropriate entry<k,v> eldest = header.after; Callback. Suppose it is necessary to remove the elements in the OLD.            The newest element is at the tail of the List.            If (removeeldestentry (eldest)) {removeentryforkey (eldest.key);            } else {if (size >= threshold) Resize (2 * table.length);            }}/** * */void createentry (int hash,k key, V value, int Bucketindex) {       hashmap.entry<k,v> old = table[bucketindex];            entry<k,v> e = new entry<k,v> (hash, key, value, old);            table[bucketindex] = e;            The essence is to insert the end of the doubly linked list E.addbefore (header);        size++; }/** * Inserted in front of existingentry because it is a doubly linked List. When Existingentry is HeaDer Time. * equivalent to inserting into the linked list at the End.

* */private void Addbefore (entry<k,v> Existingentry) {after = existingentry; Before = existingentry.before; Before.after = this; After.before = this; }



The traversal iteration uses a doubly linked list to iterate through the interface directly, not here. Be able to see the source code very easy to Understand.

Note that the implementation of the listing overrides the related build iterator method in the parent class.

TreeMap and Currenthashmap are able to write a separate article to Analyze. Here's a brief. TreeMap is based on a b-tree map, sorted by key. Currenthashmap is a powerful class in concurrent packages that is suitable for multithreading with high concurrency when data is read and Written.

A brief analysis of Java map 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.