1. Summary
In the first chapter of the collection series, we learned that the implementation class of Map has HashMap, LinkedHashMap, TreeMap, IdentityHashMap, WeakHashMap, Hashtable, Properties, etc.
#This article mainly discusses the implementation of LinkedHashMap from the data structure and algorithm level.
(Recommended learning: Java video tutorial)
2. Introduction
LinkedHashMap can be considered as HashMap LinkedList. It not only uses HashMap to operate the data structure, but also uses LinkedList to maintain the order of inserted elements. Internally, it uses a doubly-linked list (doubly-linked list) to All elements (entries) are connected.
LinkedHashMap inherits HashMap, allowing elements with a null key to be put in, and elements with a value being null to be inserted. As can be seen from the name, this container is a mixture of LinkedList and HashMap, which means that it meets certain characteristics of both HashMap and LinkedList. LinkedHashMap can be regarded as a HashMap enhanced with Linked list.
Open the LinkedHashMap source code and you can see the three main core attributes:
public class LinkedHashMap<k> extends HashMap<k> implements Map<k>{ /**双向链表的头节点*/ transient LinkedHashMap.Entry<k> head; /**双向链表的尾节点*/ transient LinkedHashMap.Entry<k> tail; /** * 1、如果accessOrder为true的话,则会把访问过的元素放在链表后面,放置顺序是访问的顺序 * 2、如果accessOrder为false的话,则按插入顺序来遍历 */ final boolean accessOrder; }</k></k></k></k></k>
LinkedHashMap In the initialization phase, the default is to traverse in the insertion order
public LinkedHashMap() { super(); accessOrder = false; }
The Hash algorithm used by LinkedHashMap and The same as HashMap, but the difference is that it redefines the element Entry saved in the array. In addition to saving the reference of the current object, the Entry also saves the reference of its previous element before and the next element after, thus in the hash table. Basically, a two-way linked list is formed.
The source code is as follows:
static class Entry<k> extends HashMap.Node<k> { //before指的是链表前驱节点,after指的是链表后驱节点 Entry<k> before, after; Entry(int hash, K key, V value, Node<k> next) { super(hash, key, value, next); } }</k></k></k></k>
It can be seen intuitively that the data inserted at the head of the doubly linked list is the entry of the linked list, and the iterator traversal direction is from the linked list starts from the head of the linked list and ends at the end of the linked list.
In addition to preserving the iteration order, this structure has another advantage: when iterating LinkedHashMap, you don’t need to traverse the entire table like HashMap, but only need to directly traverse the header pointed to. A doubly linked list is sufficient, which means that the iteration time of LinkedHashMap is only related to the number of entries and has nothing to do with the size of the table.
3. Introduction to common methods
3.1. Get method
The get method returns the corresponding value according to the specified key value . The process of this method is almost exactly the same as the HashMap.get() method. By default, it is traversed in insertion order.
public V get(Object key) { Node<k> e; if ((e = getNode(hash(key), key)) == null) return null; if (accessOrder) afterNodeAccess(e); return e.value; }</k>
If accessOrder is true, the visited elements will be placed at the end of the linked list, and the placement order is the order of access
void afterNodeAccess(Node<k> e) { // move node to last LinkedHashMap.Entry<k> last; if (accessOrder && (last = tail) != e) { LinkedHashMap.Entry<k> p = (LinkedHashMap.Entry<k>)e, b = p.before, a = p.after; p.after = null; if (b == null) head = a; else b.after = a; if (a != null) a.before = b; else last = b; if (last == null) head = p; else { p.before = last; last.after = p; } tail = p; ++modCount; } }</k></k></k></k>
Test case:
public static void main(String[] args) { //accessOrder默认为false Map<string> accessOrderFalse = new LinkedHashMap(); accessOrderFalse.put("1","1"); accessOrderFalse.put("2","2"); accessOrderFalse.put("3","3"); accessOrderFalse.put("4","4"); System.out.println("acessOrderFalse:"+accessOrderFalse.toString()); //accessOrder设置为true Map<string> accessOrderTrue = new LinkedHashMap(16, 0.75f, true); accessOrderTrue.put("1","1"); accessOrderTrue.put("2","2"); accessOrderTrue.put("3","3"); accessOrderTrue.put("4","4"); accessOrderTrue.get("2");//获取键2 accessOrderTrue.get("3");//获取键3 System.out.println("accessOrderTrue:"+accessOrderTrue.toString()); }</string></string>
Output results:
acessOrderFalse:{1=1, 2=2, 3=3, 4=4} accessOrderTrue:{1=1, 4=4, 2=2, 3=3}
3.2. Put method
The put(K key, V value) method adds the specified key, value pair to the map. This method first calls the insertion method of HashMap, and also searches the map to see if it contains the element. If it is included, it returns directly. The search process is similar to the get() method; if it is not found, the element is inserted into the collection.
/**HashMap 中实现*/ public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<k>[] tab; Node<k> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<k> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<k>)p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }</k></k></k></k>
Overridden methods in LinkedHashMap
// LinkedHashMap 中覆写 Node<k> newNode(int hash, K key, V value, Node<k> e) { LinkedHashMap.Entry<k> p = new LinkedHashMap.Entry<k>(hash, key, value, e); // 将 Entry 接在双向链表的尾部 linkNodeLast(p); return p; } private void linkNodeLast(LinkedHashMap.Entry<k> p) { LinkedHashMap.Entry<k> last = tail; tail = p; // last 为 null,表明链表还未建立 if (last == null) head = p; else { // 将新节点 p 接在链表尾部 p.before = last; last.after = p; } }</k></k></k></k></k></k>
3.3, remove method
remove(Object key) The function is to delete the entry corresponding to the key value. The implementation logic of this method is mainly based on HashMap. First, find the entry corresponding to the key value, and then delete the entry (modify the corresponding reference of the linked list). The search process is similar to the get() method. Finally, The overridden method in LinkedHashMap will be called and deleted!
/**HashMap 中实现*/ public V remove(Object key) { Node<k> e; return (e = removeNode(hash(key), key, null, false, true)) == null ? null : e.value; } final Node<k> removeNode(int hash, Object key, Object value, boolean matchValue, boolean movable) { Node<k>[] tab; Node<k> p; int n, index; if ((tab = table) != null && (n = tab.length) > 0 && (p = tab[index = (n - 1) & hash]) != null) { Node<k> node = null, e; K k; V v; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) node = p; else if ((e = p.next) != null) { if (p instanceof TreeNode) {...} else { // 遍历单链表,寻找要删除的节点,并赋值给 node 变量 do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { node = e; break; } p = e; } while ((e = e.next) != null); } } if (node != null && (!matchValue || (v = node.value) == value || (value != null && value.equals(v)))) { if (node instanceof TreeNode) {...} // 将要删除的节点从单链表中移除 else if (node == p) tab[index] = node.next; else p.next = node.next; ++modCount; --size; afterNodeRemoval(node); // 调用删除回调方法进行后续操作 return node; } } return null; }</k></k></k></k></k>
The afterNodeRemoval method overridden in LinkedHashMap
void afterNodeRemoval(Node<k> e) { // unlink LinkedHashMap.Entry<k> p = (LinkedHashMap.Entry<k>)e, b = p.before, a = p.after; // 将 p 节点的前驱后后继引用置空 p.before = p.after = null; // b 为 null,表明 p 是头节点 if (b == null) head = a; else b.after = a; // a 为 null,表明 p 是尾节点 if (a == null) tail = b; else a.before = b; }</k></k></k>
##4. Summary
LinkedHashMap inherits from HashMap. Most of the functional features are basically the same. The only difference between the two is that LinkedHashMap uses a doubly-linked list to connect all entries based on HashMap. This is to ensure that the iteration order of elements is the same as the insertion order. . The main part is exactly the same as HashMap, with the addition of header pointing to the head of the doubly linked list, and tail pointing to the tail of the doubly linked list. The default iteration order of the doubly linked list is the insertion order of the entry.Эта статья взята с китайского веб-сайта PHP, колонка Java Tutorial, добро пожаловать на обучение!
The above is the detailed content of Analysis of LinkedHashMap in simple terms (pictures and text). For more information, please follow other related articles on the PHP Chinese website!

hashmap的扩容机制是:重新计算容量,用一个新的数组替换原来的数组。重新计算原数组的所有数据并插入一个新数组,然后指向新数组;如果数组在容量扩展前已达到最大值,则直接将阈值设置为最大整数返回。

如何使用HashMap类的put()方法将键值对插入到HashMap中HashMap是Java集合框架中的一个非常重要的类,它提供了一种存储键值对的方式。在实际开发中,我们经常需要向HashMap中插入键值对,通过使用HashMap类的put()方法可以很轻松地实现这一目标。HashMap的put()方法的签名如下:Vput(Kkey,Vvalue)

Java文档解读:HashMap类的containsKey()方法用法详解,需要具体代码示例引言:HashMap是Java中常用的一种数据结构,它提供了高效的存储和查找功能。其中的containsKey()方法用于判断HashMap中是否包含指定的键。本文将详细解读HashMap类的containsKey()方法的使用方式,并提供具体的代码示例。一、cont

1、说明Map基本上可以使用HashMap,但是HashMap有一个问题,那就是迭代HashMap的顺序不是HashMap放置的顺序,就是无序。HashMap的这个缺点往往会带来麻烦,因为有些场景我们期待一个有序的Map,这就是LinkedHashMap。2、区别实例publicstaticvoidmain(String[]args){Mapmap=newLinkedHashMap();map.put("apple","苹果");map.put("

一、单例模式是什么?单例模式是一种对象创建模式,它用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例。Java里面实现的单例是一个虚拟机的范围,因为装载类的功能是虚拟机的,所以一个虚拟机在通过自己的ClassLoad装载实现单例类的时候就会创建一个类的实例。在Java语言中,这样的行为能带来两大好处:1.对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销;2.由于new操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压

Java使用HashMap类的putAll()函数将一个Map添加到另一个Map中Map是Java中常用的数据结构,用来表示键值对的集合。在Java的集合框架中,HashMap是一个常用的实现类。它提供了putAll()函数,用于将一个Map添加到另一个Map中,方便实现数据的合并和拷贝。本文将介绍putAll()函数的使用方法,并提供相应的代码示例。首先,

JavaMap是Java标准库中常用的数据结构,它以键值对的形式存储数据。Map的性能对于应用程序的运行效率至关重要,如果Map的性能不佳,可能会导致应用程序运行缓慢,甚至崩溃。1.选择合适的Map实现Java提供了多种Map实现,包括HashMap、TreeMap和LinkedHashMap。每种Map实现都有其各自的优缺点,在选择Map实现时,需要根据应用程序的具体需求来选择合适的实现。HashMap:HashMap是最常用的Map实现,它使用哈希表来存储数据,具有较快的插入、删除和查找速度

Java中使用HashMap类的keySet()方法获取映射中所有的键HashMap是Java中常用的集合类之一,它提供了一种映射关系,可以通过键值对的方式存储和访问数据。在实际开发中,我们经常需要获取HashMap中所有的键,以便进行相应的处理。而HashMap提供的keySet()方法正是用来获取映射中所有键的方法。keySet()方法是HashMap类


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

WebStorm Mac version
Useful JavaScript development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

SublimeText3 Chinese version
Chinese version, very easy to use

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Dreamweaver Mac version
Visual web development tools
