Map of the Java collection

Source: Internet
Author: User

Map is another top-level interface, the total feeling map is Collection sub-interface it. Map is primarily used to represent data that contains a mapping relationship, and stores a set of key-value pairs. Map is an associative array that allows you to associate certain objects with some other object.

For example, I would like to use a Map to store map< Integer, String > by using the student's number to find the corresponding name. I want to know how many courses each student has chosen to store Map < Student, List < Course > >. So we're going to associate the Student of this class with the classes List < Course >.

Here's what the specific implementations of the MAP's top-level interface are.

HASHMAP: It stores data based on the hashcode value of the key, which in most cases can be directly anchored to its value, and thus has a fast access speed, but the traversal order is indeterminate. HashMap allows a maximum of one record's key to be null, allowing multiple records to have a value of NULL. HashMap non-thread-safe, where multiple threads can write HashMap at any one time, may result in inconsistent data. If you need to meet thread safety, you can use the collections Synchronizedmap method to make HashMap a thread-safe capability, or use Concurrenthashmap.

Hashtable:hashtable is a legacy class, many of the common functions of mapping and HashMap similar, the difference is that it is from the Dictionary class, and is thread-safe, at any time only one thread can write Hashtable, concurrency is not as Concurrenthashmap, because Concurrenthashmap introduces a segmented lock. Hashtable is not recommended for use in new code, can be replaced with HashMap without thread safety, and can be replaced with Concurrenthashmap where thread safety is required.

Linkedhashmap:linkedhashmap is a subclass of HashMap, which preserves the order in which records are inserted, and when traversing linkedhashmap with Iterator, the first records must be inserted first, or they can be constructed with parameters. Sort by access order.

TREEMAP:TREEMAP implements the SortedMap interface, it can save the record according to the key sort, the default is the key value of ascending order, you can also specify a sort of comparator, when using Iterator traversal TREEMAP, the resulting records are ordered. If you use a sorted mapping, we recommend that you use TREEMAP. When using TREEMAP, key must implement the comparable interface or pass in a custom Comparator when constructing TreeMap, otherwise the ClassCastException type exception will be thrown at run time.

For classes of the four map types above, it is required that the key in the map is an immutable object. An immutable object is that the object's hash value is not changed after it is created. You can refer to this article to understand, String and immutable objects. If the object's hash value changes, the map object will probably not be able to locate the mapped location.

The bottom of the HashMap is mainly based on the hash table, first of all to introduce the hash of the relevant knowledge. Hash aka hash, hash table is a hash list, the appearance of the hash table is to make the data lookup becomes simple, fast, the principle is based on the hashcode value of the keyword to determine the location of the keyword storage. The calculation of the hashcode value of the method is the hash algorithm, if the different keywords to calculate the same hashcode value, then will be stored in the same position, this time there is a conflict.

We want to minimize the occurrence of conflicts under the premise of limited space, so as to ensure that our search efficiency is not affected, we need to design a good hash algorithm, and also take fully into account when there is a conflict.

Let's take a look at how the HASHMAP is designed, mainly in the hash algorithm design, the use of linked list structure and resize. First look at what the important attributes are

 Public classHashmap<k,v>extendsAbstractmap<k,v>ImplementsMap<k,v>, cloneable, serializable{//Default Length    Static Final intdefault_initial_capacity = 1 << 4;//aka//Maximum Capacity    Static Final intmaximum_capacity = 1 << 30; //default load Factor    Static Final floatDefault_load_factor = 0.75f; //Initialize to null    Static Finalentry<?,? >[] empty_table = {}; //entry array for storing key-value pairs    transiententry<k,v>[] Table = (entry<k,v>[]) empty_table; //actual length    transient intsize; //the maximum length before rehash equals Default_load_factor * default_initial_capacity    intthreshold; Final floatLoadfactor; /*** The number of times this HashMap have been structurally modified * the HashMap fail-fast.     (see Concurrentmodificationexception). */    transient intModcount; Static classEntry<k,v>ImplementsMap.entry<k,v> {        FinalK Key;        V value; Entry<K,V>Next; intHash; /*** Creates new entry. */Entry (intH, K K, v V, entry<k,v>N) {value=v; Next=N; Key=K; Hash=h; }

HashMap uses an array to represent the Hash table, and each element in the array is a entry, which is a key-value pair. When a conflict occurs, we can store multiple entry in the same location, where the structure is the linked list, and the next entry is pointed through the next entry. All of the above source code is from JDK 1.7, in JDK 1.8 entry became node nodes, and if the number of elements in the same location is greater than the threshold value of 8, the list structure will become a red black tree, the reason is that can greatly accelerate the search speed of the element.

After talking about the structure in HashMap, let's take a look at the specific operation. Mainly entry put and get process, put the process, I put a picture, the process can be at a glance.

Map.put ("name", "YJK923"); The process is to calculate the hashcode value of the name String object by using the Hashcode method (say, hashcode This method is an object object, and it is a native method) to get this hashcode value can not be directly Map array subscript store data, in order to make the data as far as possible not scattered in the same position, there is a step to the hash value and the conversion of the index value.

  Publicv put (K key, V value) {if(Table = =empty_table)        {inflatetable (threshold); }        if(Key = =NULL)            returnPutfornullkey (value); inthash =hash (key); inti =indexfor (hash, table.length);  for(entry<k,v> e = table[i]; E! =NULL; E {Object k; if(E.hash = = Hash && (k = e.key) = = Key | |Key.equals (k))) {V OldValue=E.value; E.value=value; E.recordaccess ( This); returnOldValue; }} Modcount++;        AddEntry (hash, key, value, I); return NULL; }    Static intIndexfor (intHintlength) {        returnH & (length-1); }

After reading the put look get, the Get method calculates the hash value by passing in the key value and then obtains the index value, if there are multiple elements in the same position, then use the Equals method of key to find the specified entry. Finally take out the corresponding entry, but the return to me is a value.

 PublicV get (Object key) {if(Key = =NULL)            returnGetfornullkey (); Entry<K,V> entry =getentry (key); return NULL= = entry?NULL: Entry.getvalue (); }     FinalEntry<k,v>getentry (Object key) {if(Size = = 0) {            return NULL; }        inthash = (Key = =NULL) ? 0: Hash (key);  for(Entry<k,v> e =table[indexfor (hash, table.length)]; E!=NULL; {Object k; if(E.hash = = Hash &&((k= e.key) = = Key | | (Key! =NULL&&Key.equals (k)))) returne; }        return NULL; }

Finally say the rehash process, why will appear rehash, because the actual length has reached the threshold, that is, loadfactor * capacity. The reason for setting this value is to prevent too many elements from falling into the same bucket, increasing the occurrence of conflicts and increasing the length in a timely manner. We know that the default length of HashMap is 16, and if the rehash occurs, the length is doubled directly. A new entry array is recreated in the resize process to hold the original data, and all entry will recalculate the hash value. Resize is the expansion, in the expansion of the time will be rehash.


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); }    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); }    voidTransfer (entry[] newtable,Booleanrehash) {        intNewcapacity =newtable.length;  for(entry<k,v>e:table) {             while(NULL!=e) {Entry<K,V> next; if(Rehash) {E.hash=NULL= = E.key? 0: Hash (E.key); }                inti =indexfor (E.hash, newcapacity);[i]; Newtable[i]=e; E=Next; }        }    }

By improving the hash algorithm, increasing the storage structure of the linked list, rehash and so on, we can apply the original hash table and hash algorithm to the HASHMAP in JDK 1.7, however, the function of HASHMAP is enhanced in JDK 1.8, mainly embodied in In the following 1, when the length of the list is greater than 8, the linked list is converted to a red-black tree. 2 improved the process of hashing, that is, the key mapping to the index of the process to enhance, reducing the likelihood of conflict. 3 enhancements to rehash so that it does not have to recalculate the index value of the previous entry.

Finally, there are several ways to add a traversal of the MAP:

1 Gets the collection of key KeySet.

2 Gets the collection of value Collection.

3 Gets the collection of entry EntrySet.

Set<integer> KeySet =Map.keyset (); Iterator<Integer> it2 =keyset.iterator (); while(It2.hasnext ()) {System.out.println ( ());} Collection<String> values =map.values (); Iterator<String> it =values.iterator (); while(It.hasnext ()) {System.out.println ( ());} Set<Entry<Integer,String>> EntrySet =Map.entryset (); Iterator<entry<integer, string>> iterator =entryset.iterator (); while(Iterator.hasnext ()) {Entry<integer, string> entry (); System.out.println (Entry.getkey ()+ "---->" +Entry.getvalue ());}

Finally, I want to ask, who else? JDK1.7 is still being used.

Me ~

Recommended reading: Collection of the Java collection

Reference: Re-understanding of the JAVA8 series HashMap

Related Article

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

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: and provide relevant evidence. A staff member will contact you within 5 working days.