First of all to say its characteristics, and then in one by one through the analysis of the source code to verify its implementation principle
1, can guarantee the order of inserting elements. In a bit more detail, there are two ways to iterate over elements, one is to iterate in the order in which the elements are inserted, for example, to insert A,b,c, then the iteration is A,b,c, and the other is in the order of access, for example, before the iteration, where B is accessed, the order of the iterations is a,c,b, for example, before the iteration, Then a is accessed, and then the iteration order is c,b,a, for example, B is accessed before the iteration, then B is accessed, then a is accessed, the iteration order is c,b,a. The meaning is not the most recent visit, but the last iteration, but the length of time before the iteration is determined.
2. The model of the elements stored internally. Entry is the following, compared to HashMap, two more properties, one before, one after. Next and after sometimes point to the same entry, and sometimes next points to null, and after points to entry. This specific back analysis.
3, Linkedhashmap and HashMap are the same in the store operation, but linkedhashmap many things will remember the elements inserted before this, these elements are not necessarily in a bucket, draw a picture.
that is, the basic operation for Linkedhashmap is the same as the HashMap, which adds two attributes on top of it, that is, to record the previous inserted element and an inserted element after the record. It is OK to set the values of the two properties as long as the operation is the same as HashMap. Note that there will be a header entity that is designed to record who the first inserted element is, and to find the first element when traversing. actually the storage looks like the above diagram, here to be clear oh. In fact, the storage is the same as HashMap, but at the same time adding a new thing is a two-way loop linked list. It is because of this two-way cycle linked list, linkedhashmap and HashMap is not the same.
4, some other such as how to implement the circular doubly linked list, the insertion sequence and the order of access to see the following detailed explanation.
/** * Linkedhashmap entry. */private static class Entry<k,v> extends Hashmap.entry<k,v> {//These fields comprise the doubly Linked list used for iteration. By the above interpretation of the source code, we can know that the two fields, is used for the iteration, the equivalent of a doubly linked list, in fact, the operation of the Linkedhashmap entry and Operation HashMap entry is the same, only the same four properties, These two fields are manipulated by some methods in Linkedhashmap. So many methods of Linkedhashmap are directly inherited from HashMap. Before: points to the previous entry element. After: Point to the last Entry element entry<k,v> before, after; Using the HashMap Entry construct, call the parent class constructor Entry (int hash, K key, V value, hashmap.entry<k,v> next) {Super (has h, key, value, next); }//Delete the current entry private void Remove () {before.after = after; After.before = before; }//usually comes in the header, inserts the current Entry (that is, this) into the end of the list, and updates the four reference relationship private void Addbefore (entry<k,v> existinge ntry) {after = Existingentry; before = Existingentry.before; Before.after = this; After.before = this; }//In the LRU algorithm, most rarely accessed elements are ranked in the front of the two-way loop list, and frequently accessed elements are generally in the back of the doubly linked list, and these functions are dependent on the method. When the current entry is accessed, we call this method, first delete the current list of
This (that is, entry), then re-add this to the end of the list by the Addbefore method, and update the four references (of course this is the process in the Addbefore), so that the access to the element is transferred to the tail, reached the state of the active update void Recordaccess (hashmap<k,v> m) {linkedhashmap<k,v> LM = (linkedhashmap<k,v>) m; if (lm.accessorder) {lm.modcount++; Remove (); Addbefore (Lm.header); }} void Recordremoval (hashmap<k,v> m) {remove (); } }
This is followed by common methods, such as the Put method (which is inherited from HashMap):
Public V put (K key, V value) { if (table = = empty_table) { inflatetable (threshold); } if (key = = null) return Putfornullkey (value); int hash = hash (key); int i = indexfor (hash, table.length); for (entry<k,v> e = table[i]; E! = null; e = e.next) { Object K; if (E.hash = = Hash && (k = e.key) = = Key | | key.equals (k))) { V oldValue = e.value; E.value = value; If the entry exists, change the value directly, and then move the entry to the end e.recordaccess (this); return oldValue; } } modcount++;
Note that the AddEntry method here is linkedhashmap covered, so the call is actually Linkedhashmap addentry addentry (hash, key, value, I); return null; }
Linkedhashmap source code and LRU algorithm application