LinkedHashMap源码剖析

前言

HashMap,比如你放了一堆key-value对进去,后面的话呢如果你要遍历这个HashMap的话,遍历的顺序,并不是按照你插入的key-value的顺序来的

LinkedHashMap,他会记录你插入key-value的顺序, 如果你在遍历的时候,他是按照插入key-value对的顺序给你遍历出来的

LinkedHashMap是HashMap的一个子类。LinkedHashMap和TreeMap的区别,他们都可以维持key的顺序,只是LinkedHashMap底层是基于链表来实现的,TreeMap是基于红黑树来实现顺序的

LinkedHashMap其实原则上来说一些基本的原理和操作跟HashMap是差不多的,唯一主要的区别就是你在插入、覆盖、删除,他会记录一下key-value对的顺序,用一个链表来记录,在遍历的时候,就可以按照这个顺序来遍历

源码剖析

在调用LinkedHashMap的put()方法的时候,一定会调用到HashMap的put()方法里面去,调用完put()方法,其实就会调用afterNodeInsertion(evict);,这个方法就会去回调LinkedHahsMap里面的子类的实现。

void afterNodeInsertion(boolean evict) { // possibly remove eldest

        LinkedHashMap.Entry<K,V> first;

        if (evict && (first = head) != null && removeEldestEntry(first)) {

            K key = first.key;

            removeNode(hash(key), key, null, false, true);

        }

}

所以说就是在这里,回调了这个方法,这个方法里面,他就是实现了LinkedHashMap的逻辑,来记录插入key-value对的顺序,用一个链表来记录。

    Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {

        LinkedHashMap.Entry<K,V> p =

            new LinkedHashMap.Entry<K,V>(hash, key, value, e);

        linkNodeLast(p);

        return p;

    }

将节点封装为了一个LinkedHashMap.Entry对象,然后使用linkNodeLast(p)这个东西,将这个节点挂到一个链表里去。

LinkedHashMap有一个参数的,你可以在构造的时候传入进去,accessOrder,默认他是false,如果是默认为false的话,那么你比如说你get一个key,或者是覆盖这个key的值,都不会改变他在链表里的顺序。

但是如果accessOrder是true的话,那么如果你get一个key,或者是覆盖这个key的值,就会导致个key-value对顺序会在链表里改变,他会被挪动到链表的尾部去

你删除某个元素的时候,就会将那个元素从链表里给摘除

在迭代的时候,LinkedHashMap里面会从链表的头部开始迭代,这样通过这个链表就可以维持他的一个顺序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章