Thinking Logic of computer programs (49)-Anatomy Linkedhashmap

Source: Internet
Author: User
Tags null null

Before we introduced the two implementation classes HashMap and TreeMap of the map interface, this section describes another implementation class Linkedhashmap. It is a subclass of HashMap, but it can keep elements in order by inserting or accessing them, which is different from the TreeMap key ordering.

By inserting orderly easy to understand, according to the order of access what does it mean? What is the use of these two order? How is the interior implemented? This section explores these issues. Start with the usage.

Usage

Basic concepts

Linkedhashmap is a subclass of HashMap, but there is also a two-way list that maintains the order of key-value pairs, with each key-value pair located in the hash table and also in the doubly linked list.

Linkedhashmap supports two kinds of order, one is the insertion order and the other is the access order.

The insertion order is easy to understand, first added in the front, and then added later, and the modification does not affect the order.

What does the order of access mean? The so-called Access refers to the get/put operation, the corresponding key-value pair will be moved to the end of the list after performing a get/put operation on a key, so the most recent access is the most recently accessed, the first of which is not accessed, which is the order of access.

Linkedhashmap has five construction methods, of which four are in the order of insertion, as follows:

 Public Linkedhashmap ()  Public Linkedhashmap (int  initialcapacity) public linkedhashmap (intfloat  Loadfactor)publicextendsextends v> m)

There is only one construction method that you can specify in order of access, as follows:

 Public Linkedhashmap (int  initialcapacity,                     float  loadfactor,                     Boolean Accessorder)

Where the parameter accessorder is used to specify whether in the order of access, if true, is the order of access.

Below, let's look at some simple examples.

Press Insert to order

By default, Linkedhashmap is ordered by insert, and we look at the code:

New Linkedhashmap<> (); Seqmap.put("C", +), Seqmap.put ("D", "a");seqmap.put ("a", 500 ); Seqmap.put ("D", +) ;  for (entry<string,integer> Entry:seqMap.entrySet ()) {    System.out.println (Entry.getkey ()+ "" +  Entry.getvalue ());}

The keys are inserted in the order of "C", "D", "a", and the value of "D" is not modified in order, so the output is:

C500

When do you want to keep the insertion order?

Map is often used to process some data, its processing mode is to accept some key value pairs as input, processing, and then output, the output would like to maintain the original order. For example, a configuration file, which has some key-value pairs in the form of configuration items, but some of the keys are duplicated, want to keep the last value, but still in the original key sequence output, Linkedhashmap is a suitable data structure.

For example, the desired data model may be a map, but want to keep the order of additions, such as a shopping cart, key for the purchase of items, the value of the purchase quantity, in the order of the user added to save.

Another common scenario is that you want the map to be keyed in order, but before you add it to the map, the key has already been sorted by other means, and there is no need to use TreeMap, after all, the cost of TreeMap is bigger. For example, when you put data from a database into memory, you can use the SQL ORDER BY statement to have the database sort the data.

Ordered by Access

Let's take a look at an orderly example with the following code:

New true ); Accessmap.put ("C", [+]),accessmap.put ("D", "a"),Accessmap.put ("A", "a"); Accessmap.get ("C"); Accessmap.put ("D");  for (entry<string,integer> Entry:accessMap.entrySet ()) {    System.out.println (Entry.getkey ()+ "" + Entry.getvalue ());}

Each access moves the key-value pair to the end, so the output is:

a300

When do you want to order it? A typical application is the LRU cache, what is it?

LRU Cache

Cache is a very useful technique in computer technology, is a general idea to improve the performance of data access, generally used to save commonly used data, smaller capacity, but faster access, the cache is relatively relative to main memory, memory capacity is larger, but more slow access. The basic assumption of the cache is that the data will be accessed multiple times, the general access to data, the first from the cache, the cache is not found in main memory, found, and then put into the cache, so that the next time if the same data, access is fast.

Caches are used in various areas of computer technology, such as cache in the CPU, first-level cache, level two cache, level three cache, and so on, a very small cache, very expensive, very fast, a three-level cache is larger, cheaper, and slower, and the CPU cache is faster than memory compared to memory. Memory also has a cache, the memory of the cache is generally relative to the hard disk data. A hard disk can also be cached, caching data from other machines on the network, such as when a browser accesses a webpage, and caches some pages to the local hard disk.

Linkedhashmap can be used for caching, such as caching the user's basic information, the key is the user ID, the value is the user information, all the user's information may be saved in the database, some of the active user's information may be in the cache.

In general, the cache capacity is limited, can not store all the data indefinitely, if the cache is full, when the need to store new data, it is necessary to a certain policy to clean up some old data, this strategy is generally called the replacement algorithm. LRU is a popular replacement algorithm, its full name is least recently used, the least recently used, it is the idea is that the most recently used is the most likely to be used again soon, and the longest not accessed soon again is the least likely to be used, so is prioritized cleanup.

With Linkedhashmap, it is very easy to implement the LRU cache, by default, Linkedhashmap does not limit capacity, but it can be easily done, it has a protected method, as follows:

protected boolean removeeldestentry (map.entry<k,v> eldest) {    returnfalse;}

After adding the element to Linkedhashmap, Linkedhashmap will call this method, passing the parameter is the longest not accessed key value pair, if this method returns True, then the longest key value pair will be deleted. The implementation of Linkedhashmap always returns false, all capacity is unlimited, but subclasses can override the method, returning true if certain conditions are met.

Here is a simple implementation of the LRU cache, which has a capacity limit, which is passed in the construction method, and the code is:

 Public classLrucache<k, v>extendsLinkedhashmap<k, v> {    Private intmaxentries;  PublicLRUCache (intmaxentries) {        Super(0.75f,true);  This. maxentries =maxentries; } @Overrideprotected BooleanRemoveeldestentry (Entry<k, v>eldest) {        returnSize () >maxentries; }}    

This cache can be used in this way:

New Lrucache<> (3); Cache.put ("A", "abstract"), Cache.put ("B", "basic"), Cache.put ("C", "Call");Cache.get ("a"); Cache.put ("D", "call"); SYSTEM.OUT.PRINTLN (cache);

Limited cache capacity of 3, has added 4 key-value pairs, the longest time not accessed by the key is "B", will be deleted, so the output is:

{c=call, a=abstract, D=call}

Implementation principle

Understanding the use of linkedhashmap, let's look at its implementation code. As for the code, we explain that this series of articles, if no additional instructions, are based on JDK 7.

Internal composition

Linkedhashmap is a subclass of HashMap, and the following instance variables are added internally:

Private transient entry<k,v> header; Private Final boolean Accessorder;

Accessorder indicates whether the order of access or insertion is in order. The header represents the head of the doubly linked list, its type entry is an inner class, the class is a subclass of Hashmap.entry, adds two variables before and after, points to the predecessor and successor in the list, and entry's complete definition is:

Private Static classEntry<k,v>extendsHashmap.entry<k,v>{Entry<K,V>before, after; Entry (intHash, K key, V value, hashmap.entry<k,v>next) {        Super(hash, key, value, next); }    Private voidRemove () {Before.after=After ; After.before=before; }    Private voidAddbefore (entry<k,v>existingentry) { After=Existingentry; Before=Existingentry.before; Before.after= This; After.before= This; }    voidRecordaccess (hashmap<k,v>m) {Linkedhashmap<K,V> lm = (linkedhashmap<k,v>) m; if(lm.accessorder) {Lm.modcount++;            Remove ();        Addbefore (Lm.header); }    }    voidRecordremoval (hashmap<k,v>m) {remove (); }}

Recordaccess and Recordremoval are methods defined in Hashmap.entry, where the implementations of these two methods are empty, they are designed to be overridden by the quilt class, and when the put is called and the key exists, HashMap calls entry Recordac Cess method, when the key is deleted, HashMap calls entry's Recordremoval method.

Linkedhashmap.entry overrides both methods, in recordaccess, if in order of access, the node is moved to the end of the list, and in Recordremoval, the node is removed from the list.

Understanding the internal composition, we look at the operation method, first look at the construction method.

Construction method

In the HashMap constructor method, the Init method is called, and the Init method is empty in the implementation of the HashMap and is designed to be rewritten. Linkedhashmap overrides the method, which initializes the head node of the linked list, with the following code:

void init () {    newnull-null null)    ; = Header.after = header;}

The header is initialized to a entry object, and both precursors and successors point to themselves, as shown in:


Header.after points to the first node, Header.before points to the last node, and pointing to the header indicates that the list is empty.

Put method

In Linkedhashmap, the Put method also joins the node to the list, and if it is ordered, the node is adjusted to the end, and the node that is not accessed for the longest time is deleted as appropriate.

In the put implementation of HashMap, if it is a new key, the AddEntry method is called to add the node, Linkedhashmap overrides the method, and the code is:

void addentry (intint  bucketindex) {    super. AddEntry (hash, key, Value, Bucketindex);     // Remove eldest entry if instructed    entry<k,v> eldest = header.after;     if (Removeeldestentry (eldest)) {        removeentryforkey (eldest.key);    }}

It calls the parent class's AddEntry method first, the parent class's addentry calls Createentry to create the node, Linkedhashmap overrides Createentry, and the code is:

void createentry (intint  bucketindex) {    hashmap.entry<K,V> old =  Table[bucketindex];    EntryNew entry<>(hash, key, value, old);     = E;    E.addbefore (header);    Size+ +;}

Create a new node, add the hash table, add the list, and add the code to the end of the list:

E.addbefore (header)

For example, execute the following code:

New Linkedhashmap<>(); Countmap.put ("Hello", 1);

After execution, the diagram structure is as follows:


After adding, call Removeeldestentry to check if the old node should be removed, if the return value is true, call Removeentryforkey to delete, Removeentryforkey is the method defined in HashMap. Deleting a node calls Hashmap.entry's Recordremoval method, which is overridden by linkedhashmap.entry and removes the node from the linked list.

In HashMap's put implementation, if the key already exists, the node's Recordaccess method is called, Linkedhashmap.entry overrides the method, and if it is ordered by access, the node is adjusted to the end of the list.

Get method

Linkedhashmap overrides the Get method, and the code is:

 Public V get (Object key) {    Entry<K,V> e = (entry<k,v>) getentry (key);     if NULL )        returnnull;    E.recordaccess (this);     return E.value;}

The difference between the Get method and HashMap, mainly called the Recordaccess method of the node, if it is ordered by access, recordaccess Adjust the node to the end of the list.

See if a value is included

Looking at whether a value is included in the HashMap needs to be traversed, since Linkedhashmap maintains a separate linked list, it can use a linked list for more efficient traversal, Containsvalue code is:

 Public BooleanContainsvalue (Object value) {//overridden to take advantage of faster iterator    if(value==NULL) {         for(Entry e = Header.after; E! = header; e =e.after)if(e.value==NULL)                return true; } Else {         for(Entry e = Header.after; E! = header; e =e.after)if(Value.equals (e.value))return true; }    return false;}

The code is relatively simple and does not explain it.

Principle Summary

The above is the basic realization principle of linkedhashmap, it is the subclass of HashMap, Its node class Linkedhashmap.entry is a subclass of Hashmap.entry, Linkedhashmap internally maintains a separate doubly linked list, each node is in a hash table, also in a doubly linked list, the order in the list by default is the insertion order, or can be configured as the Access order, link Edhashmap and its node class Linkedhashmap.entry override several methods to maintain this relationship.

Linkedhashset

Prior to the introduction of the map interface implementation class has a corresponding set interface implementation class, such as HashMap have Hashset,treemap have Treeset,linkedhashmap is no exception, It also has an implementation class Linkedhashset corresponding to the set interface. Linkedhashset is a subclass of HashSet, but its internal map implementation class is Linkedhashmap, so it can also keep the insertion order, such as:

New Linkedhashset<>(), Set.add ("B"), Set.add ("C"),Set.add ("a"); Set.add ("C" ); SYSTEM.OUT.PRINTLN (set);

The output is:

[B, C, a]

The implementation of Linkedhashset is relatively simple, we will no longer introduce.

Summary

This section mainly introduces the usage and implementation principle of linkedhashmap, it can keep the insertion order or the access order, the insertion order is often used to process the data of key-value pairs, and keep their input order, also often used for the key is already sequenced scene, compared to treemap more efficient, The access order is often used to implement the LRU cache. In principle, it is a subclass of HashMap, but internally there is a doubly linked list to maintain the order of the nodes.

Finally, we briefly introduce Linkedhashset, which is a subclass of HashSet, but uses linkedhashmap internally.

If you need a map implementation class, and the type of the key is an enumeration type, you can use HashMap, but you should use a dedicated implementation class Enummap, why? Let's discuss it in the next section.

----------------

To be continued, check out the latest articles, please pay attention to the public number "old Horse Programming" (Scan the QR code below), from the introduction to advanced, in layman's words, Lao Ma and you explore the nature of Java programming and computer technology. Original intentions, All rights reserved.

Thinking Logic of computer programs (49)-Anatomy Linkedhashmap

Related Article

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.