LinkedHashMap is so simple [source code analysis]

foreword

Statement, this article uses jdk1.8

I have already talked about the overview and analysis of the Collection List collection, as well as the hash table, Map collection, red-black tree and HashMap foundation:

This article mainly explains LinkedHashMap ~

Before reading this article, it is best to have a little bit of data structure basics:

Of course, if there is something wrong, please bear with me and correct me in the comments~

1. Analysis of LinkedHashMap

LinkedHashMap data structure diagram:

 

 

ps: picture source network, invade and delete~

First let's take a look at the class inheritance diagram:

 

 

I simply translated the comments at the top (my English level is slag, please bear with me if there are any mistakes~ Welcome to correct me in the comment area)

 

 

From the top translation, we can summarize the HashMap points:

  • The bottom layer is a hash table and a doubly linked list
  • null allowed, not synchronized
  • The order of insertion is ordered (the underlying linked list makes it ordered)
  • The loading factor and initial capacity have a great impact on LinkedHashMap~

It also brought me a few questions:

  • The specific use and meaning of access-ordered and insertion-ordered
  • Why is it said that the initial capacity has no effect on the traversal?

I hope that I can solve these two questions in the process of looking at the source code~ Then let's start ~

1.1 Domain of LinkedHashMap

 

 

1.2 Rewritten method of LinkedHashMap

Here are the two most important ones:

 

 

This confirms that the bottom layer of our LinkedHashMap is indeed a hash table and a doubly linked list ~

  • When building a new node, what is built is LinkedHashMap.Entryno longer Node.

1.3 Construction method

It can be found that LinkedHashMap has 5 constructors :

 

 

Let's take a look at what the definition of the constructor looks like:

 

 

What we can know from the construction method is: LinkedHashMap uses the insertion order by default

1.4 put method

Originally, I wanted to find the put method and see how it was implemented. Later, I didn't find it, and it was strange ~

 

 

After a pause, it turns out that the put methods of LinkedHashMap and HashMap are the same! LinkedHashMap inherits HashMap, LinkedHashMap does not override the put method of HashMap

Therefore, the put method of LinkedHashMap is the same as HashMap.

If you haven't seen HashMap is so simple [source code analysis] , you can go in and have a look~

Of course, when creating a node, the method overridden by LinkedHashMap is called ~

 

 

1.5 get method

 

 

 

 

There are also more get methods: judging whether it is an access order ~~~

Having said that, it feels like we can simply test a wave:

First we look at the inserted order for insertion and traversal:


    public static void insertOrder() {

        // 默认是插入顺序
        LinkedHashMap<Integer,String>  insertOrder = new LinkedHashMap();

        String value = "关注公众号Java3y";
        int i = 0;

        insertOrder.put(i++, value);
        insertOrder.put(i++, value);
        insertOrder.put(i++, value);
        insertOrder.put(i++, value);
        insertOrder.put(i++, value);

        //遍历
        Set<Integer> set = insertOrder.keySet();
        for (Integer s : set) {
            String mapValue = insertOrder.get(s);
            System.out.println(s + "---" + mapValue);
        }
    }

Test a wave:

 

 

Next, let's test insertion and traversal in access order :

    public static void accessOrder() {
        // 设置为访问顺序的方式
        LinkedHashMap<Integer,String> accessOrder = new LinkedHashMap(16, 0.75f, true);

        String value = "关注公众号Java3y";
        int i = 0;
        accessOrder.put(i++, value);
        accessOrder.put(i++, value);
        accessOrder.put(i++, value);
        accessOrder.put(i++, value);
        accessOrder.put(i++, value);


        // 遍历
        Set<Integer> sets = accessOrder.keySet();
        for (Integer key : sets) {
            String mapValue = accessOrder.get(key);
            System.out.println(key + "---" + mapValue);
        }

    }

The code seems to be no problem, but the operation will go wrong!

 

 

When we looked at the source code comments earlier, we found that: in the case of AccessOrder, using the get method is also a structural modification !

In order to simply see the difference between the two, I will use the key to see it directly below ~

Here is a test of the access order :



    public static void accessOrder() {
        // 设置为访问顺序的方式
        LinkedHashMap<Integer,String> accessOrder = new LinkedHashMap(16, 0.75f, true);

        String value = "关注公众号Java3y";
        int i = 0;
        accessOrder.put(i++, value);
        accessOrder.put(i++, value);
        accessOrder.put(i++, value);
        accessOrder.put(i++, value);
        accessOrder.put(i++, value);


        // 访问一下key为3的元素再进行遍历
        accessOrder.get(3);

        // 遍历
        Set<Integer> sets = accessOrder.keySet();
        for (Integer key : sets) {

            System.out.println(key );
        }

    }

Test Results:

 

 

The following is a test of the insertion order (the code will not be posted, it is almost the same as above):

 

 

We can understand it this way: the most commonly used ones are placed at the end of the linked list, and the less commonly used ones are placed at the top of the linked list ~

As far as I understand this knowledge point, its access order is not very useful in LinkedHashMap if it is not rewritten ~ It is used to extend other implementations

  • Because the most commonly used elements are placed at the end when they are traversed, I have not found a corresponding method to call in LinkedHashMap ~
  • A removeEldestEntry(Map.Entry<K,V> eldest)method, override it to remove the oldest unused element ! !
  • There is also a afterNodeInsertion(boolean evict)method to determine whether to delete the element that has not been used for the longest time when adding ! !

 

 

I searched for a few articles on the Internet, all of which are about the implementation of LRUMap (that is, the extension of LinkedHashMap). Interested students can refer to the following links:

1.6 remove method

For the remove method, it is not overridden in LinkedHashMap. It still calls the remove()method of the parent class's HashMap. What is overridden in LinkedHashMap is: afterNodeRemoval(Node<K,V> e)this method

 

 

Of course, the above rewritten method will be involved when remove:

 

 

1.7 The method of traversal

Set<Map.Entry<K,V>> entrySet()was rewritten

 

 

 

 

Seeing this, we know why the comment says: the initial capacity has no effect on traversal

Because it traverses a doubly linked list maintained internally by LinkedHashMap , not a hash table (of course, the elements of the linked list doubly linked list are derived from the hash table)

2. Summary

LinkedHashMap has one more doubly linked list maintenance than HashMap. It is more complicated in terms of data structure, and it is easier to read the source code, because most of them are implemented by HashMap..

When reading the source code, we will find that polymorphism is ubiquitous. The subclass uses the method of the parent class, and the subclass rewrites some methods of the parent class to achieve different effects!

  • For example: LinkedHashMap does not override the put method, but the method inside the put method is newNode()overridden. LinkedHashMap calls the put method of the parent class, and the callback inside is rewritten newNode(), so as to achieve the purpose!

LinkedHashMap can set two traversal orders:

  • access-ordered
  • insertion-ordered
  • The default is insertion order

For access order, it is an implementation of the LRU (least recently used) algorithm. To use it, either rewrite several methods ( removeEldestEntry(Map.Entry<K,V> eldest)and afterNodeInsertion(boolean evict)) of LinkedListMap, or extend it to LRUMap, or set it to access-ordered. Not very useful~

LinkedHashMap traverses an internally maintained doubly linked list , so the initial capacity is not affected by LinkedHashMap traversal

References:

If there is no accident tomorrow, I may write TreeMap, so stay tuned~~~~

 

 

Article directory navigation : zhongfucheng.bitcron.com/post/shou-j…

If there are any mistakes in the article, please correct me, and we can communicate with each other. Students who are used to reading technical articles on WeChat and want to get more Java resources can follow WeChat public account: Java3y . For everyone's convenience, I just created a new QQ group: 742919422 , you can also go to communicate. Thank you for your support! Hope to introduce more to other friends in need

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324381281&siteId=291194637