• LinkHashMap源码详解


    一、成员变量

    private transient Entry<K,V> header;//循环双向链表的头

    二、构造方法

    LinkHashMap的构造方法和HashMap的构造方法一样,但是重写init()方法;

        @Override
        void init() {
            header = new Entry<>(-1, null, null, null);
            //将元素的前驱和后续都指向自己,图解
            header.before = header.after = header;
        }

    这里写图片描述

    put方法

    put方法和hashMap的方法大致相似,不过重写了addEntry方法,主要介绍addEntry方法

        void addEntry(int hash, K key, V value, int bucketIndex) {
            //调用父类的addEntry方法,但是重写了createEntry方法
            super.addEntry(hash, key, value, bucketIndex);
    
            // Remove eldest entry if instructed
            Entry<K,V> eldest = header.after;
            if (removeEldestEntry(eldest)) {
                removeEntryForKey(eldest.key);
            }
        }
    
    
        void createEntry(int hash, K key, V value, int bucketIndex) {
            HashMap.Entry<K,V> old = table[bucketIndex];
            Entry<K,V> e = new Entry<>(hash, key, value, old);
            table[bucketIndex] = e;
            //主要看这个方法,把链表头传进去
            e.addBefore(header);
            size++;
        }
     private void addBefore(Entry<K,V> existingEntry) {
                //图解
                after  = existingEntry;
                before = existingEntry.before;
                before.after = this;
                after.before = this;
            }

    第一次添加新的结点不是很好体现出循环双向链表
    这里写图片描述
    第二次添加新的结点
    这里写图片描述

    remove方法

    remove和hashMap的remove的方法很像,不过LinkedHashMap重写了e.recordRemoval(this);这个方法

            private void remove() {
                //下面的代码相当于这样的,加个this比较好理解
                //this.before.after = this.after;
                //this.after.before = this.before;
    
                //源码
                before.after = after;
                after.before = before;
            }

    这里写图片描述

    迭代器

        private abstract class LinkedHashIterator<T> implements Iterator<T> {
            Entry<K,V> nextEntry    = header.after;
            Entry<K,V> lastReturned = null;
            int expectedModCount = modCount;
    
            //如果结点不等于链表头,那么说明还有元素
            public boolean hasNext() {
                return nextEntry != header;
            }
    
            public void remove() {
                if (lastReturned == null)
                    throw new IllegalStateException();
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
    
                LinkedHashMap.this.remove(lastReturned.key);
                lastReturned = null;
                expectedModCount = modCount;
            }
    
            Entry<K,V> nextEntry() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                if (nextEntry == header)
                    throw new NoSuchElementException();
    
                Entry<K,V> e = lastReturned = nextEntry;
                nextEntry = e.after;
                return e;
            }
        }
  • 相关阅读:
    Vs2010程序和数据库打包成安装文件
    转——C# DataGridView控件 动态添加新行
    c# WinForm开发 DataGridView控件的各种操作
    转——使用PowerDesigner画ER图
    C#画图
    DataGridView 取得当前单元格的内容实现模糊查找
    DataGridView 取得或者修改当前单元格的内容
    c# 做了个Form,上面有个Button,如何在Form加载好之后,用代码触发这个Button的Click事件
    一次ORACLE连接报错
    再次学习Django,实现sql的页面显示及条件查询
  • 原文地址:https://www.cnblogs.com/aotemanzhifu/p/9192366.html
Copyright © 2020-2023  润新知