search
HomeJavajavaTutorialAnalysis of LinkedHashMap in simple terms (pictures and text)

Analysis of LinkedHashMap in simple terms (pictures and text)

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.

Analysis of LinkedHashMap in simple terms (pictures and text)

#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>

Analysis of LinkedHashMap in simple terms (pictures and text)

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.

Analysis of LinkedHashMap in simple terms (pictures and text)

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>

Analysis of LinkedHashMap in simple terms (pictures and text)

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>

Analysis of LinkedHashMap in simple terms (pictures and text)

##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!

Statement
This article is reproduced at:博客园. If there is any infringement, please contact admin@php.cn delete
hashmap的扩容机制是什么hashmap的扩容机制是什么Mar 15, 2023 pm 03:39 PM

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

如何使用HashMap类的put()方法将键值对插入到HashMap中如何使用HashMap类的put()方法将键值对插入到HashMap中Jul 26, 2023 pm 11:53 PM

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

Java文档解读:HashMap类的containsKey()方法用法详解Java文档解读:HashMap类的containsKey()方法用法详解Nov 04, 2023 am 08:12 AM

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

java中LinkedHashMap和HashMap区别是什么java中LinkedHashMap和HashMap区别是什么May 02, 2023 am 08:31 AM

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

Java单例模式怎么利用HashMap实现缓存数据Java单例模式怎么利用HashMap实现缓存数据May 13, 2023 am 09:43 AM

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

Java使用HashMap类的putAll()函数将一个Map添加到另一个Map中Java使用HashMap类的putAll()函数将一个Map添加到另一个Map中Jul 24, 2023 am 09:36 AM

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

Java Map 性能优化揭秘:让你的数据操作更快速、更高效Java Map 性能优化揭秘:让你的数据操作更快速、更高效Feb 20, 2024 am 08:31 AM

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

Java中使用HashMap类的keySet()方法获取映射中所有的键Java中使用HashMap类的keySet()方法获取映射中所有的键Jul 24, 2023 pm 12:24 PM

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

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Safe Exam Browser

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

Dreamweaver Mac version

Visual web development tools