zoukankan      html  css  js  c++  java
  • JDK源码学习笔记——LinkedHashMap

    HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序。

    LinkedHashMap保证了元素迭代的顺序。该迭代顺序可以是插入顺序或者是访问顺序。通过维护一个双向链表实现。

    需要在理解HashMap实现原理的基础上学习LinkedHashMap,JDK源码学习笔记——HashMap

    一、数据结构

    实际上就是在HashMap的基础上加了LinkedList

    (图片来自Java集合之LinkedHashMap

    LinkedHashMap.Entry继承了HashMap.Node,并扩展了before ,after属性

        static class Entry<K,V> extends HashMap.Node<K,V> {
            Entry<K,V> before, after;
            Entry(int hash, K key, V value, Node<K,V> next) {
                super(hash, key, value, next);
            }
        }

    二、类

    继承了HashMap

    public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>

     三、属性

        transient LinkedHashMap.Entry<K,V> head;
        transient LinkedHashMap.Entry<K,V> tail;
        final boolean accessOrder;//true表示按照访问顺序迭代(最近访问在后),false时表示按照插入顺序(先插入在前,默认)

    四、主要方法

    put

        /**
         * 直接使用HashMap的put方法
         * 重写了newNode()方法:维护双向链表
         * 重写了afterNodeAccess(e)方法:如果按访问顺序排序,把node移动到双链表的尾端
         */
        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;
        }
        private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
            LinkedHashMap.Entry<K,V> last = tail;
            tail = p;
            if (last == null)
                head = p;
            else {
                p.before = last;
                last.after = p;
            }
        }
        
        void afterNodeAccess(Node<K,V> e) { // move node to last
            LinkedHashMap.Entry<K,V> last;
            if (accessOrder && (last = tail) != e) {
                LinkedHashMap.Entry<K,V> p =
                    (LinkedHashMap.Entry<K,V>)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;
            }
        }

    get

        /**
         * 重写了get方法
         * 如果按访问顺序排序,把node移动到双链表的尾端
         */
        public V get(Object key) {
            Node<K,V> e;
            if ((e = getNode(hash(key), key)) == null)
                return null;
            if (accessOrder)
                afterNodeAccess(e);// 如果按访问顺序排序,把node移动到双链表的尾端
            return e.value;
        }

    remove

        /**
         * 直接使用HashMap的remove方法
         * 重写了afterNodeRemoval()方法:维护双端链表
         */
        void afterNodeRemoval(Node<K,V> e) { // unlink
            LinkedHashMap.Entry<K,V> p =
                (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
            p.before = p.after = null;
            if (b == null)
                head = a;
            else
                b.after = a;
            if (a == null)
                tail = b;
            else
                a.before = b;
        }

    遍历

        /**
         * 主要看nextNode()方法
         * 直接遍历的双向链表
         */
        final class LinkedKeyIterator extends LinkedHashIterator implements Iterator<K> {
            public final K next() {
                return nextNode().getKey();
            }
        }
    
        final class LinkedValueIterator extends LinkedHashIterator implements Iterator<V> {
            public final V next() {
                return nextNode().value;
            }
        }
    
        final class LinkedEntryIterator extends LinkedHashIterator implements Iterator<Map.Entry<K, V>> {
            public final Map.Entry<K, V> next() {
                return nextNode();
            }
        }
        
        abstract class LinkedHashIterator {
            LinkedHashMap.Entry<K,V> next;
            LinkedHashMap.Entry<K,V> current;
            int expectedModCount;
    
            LinkedHashIterator() {
                next = head;
                expectedModCount = modCount;
                current = null;
            }
    
            public final boolean hasNext() {
                return next != null;
            }
    
            final LinkedHashMap.Entry<K,V> nextNode() {
                LinkedHashMap.Entry<K,V> e = next;
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                if (e == null)
                    throw new NoSuchElementException();
                current = e;
                next = e.after;
                return e;
            }
    
            public final void remove() {
                Node<K,V> p = current;
                if (p == null)
                    throw new IllegalStateException();
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                current = null;
                K key = p.key;
                removeNode(hash(key), key, null, false, false);
                expectedModCount = modCount;
            }
        }

     

  • 相关阅读:
    Python零基础入门的基础案例
    今天不抠图,Python实现一键换底片!想换什么换什么(附源码)
    python基础:如何使用 pip 安装第三方库
    Python教程:matplotlib 绘制双Y轴曲线图
    福利来啦,送给大家一个小游戏的源码,不要错过哟
    招聘信息太多,哪家职位才是适合你的?Python采集招聘信息
    我的python菜鸟之路1
    我的SAS菜鸟之路3
    我的SAS菜鸟之路2
    猪鹿蝶1
  • 原文地址:https://www.cnblogs.com/hexinwei1/p/9723800.html
Copyright © 2011-2022 走看看