• jdk源码——linkedHashMap——jdk1.7


     LinkedHashMap的定义

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

      private transient Entry<K,V> header;//头结点

       private final boolean accessOrder;//为false时按插入顺序排序,根据构造方法来看基本上都是调用hashMap的构造方法,accessOrder都为false,默认插入顺序排序

     根据下面的Entry的定义 画出LinkedHashMap的数据结构

     

    可以更加形象的描绘成这样

        private static class Entry<K,V> extends HashMap.Entry<K,V> {
            // These fields comprise the doubly linked list used for iteration.
            Entry<K,V> before, after;

            Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
                super(hash, key, value, next);
            }

            /**
             * Removes this entry from the linked list.
             */
            private void remove() {
                before.after = after;
                after.before = before;
            }

            /**
             * Inserts this entry before the specified existing entry in the list.
             */
            private void addBefore(Entry<K,V> existingEntry) {
                after  = existingEntry;
                before = existingEntry.before;
                before.after = this;
                after.before = this;
            }

            /**
             * This method is invoked by the superclass whenever the value
             * of a pre-existing entry is read by Map.get or modified by Map.set.
             * If the enclosing Map is access-ordered, it moves the entry
             * to the end of the list; otherwise, it does nothing.
             */
            void recordAccess(HashMap<K,V> m) {
                LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
                if (lm.accessOrder) {
                    lm.modCount++;
                    remove();
                    addBefore(lm.header);
                }
            }

            void recordRemoval(HashMap<K,V> m) {
                remove();
            }
        }

     LinkedHashMap,重写了addEntry方法和creatEntry方法,

     void addEntry(int hash, K key, V value, int bucketIndex) {
            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++;
        }

     HashMap遍历时,按哈希表的每一个索引的链表从上往下遍历,由于HashMap的存储规则,最晚添加的节点都有可能在第一个索引的链表中,这就造成了HashMap的遍历时无序的,而linkedhashMap是从头结点遍历的

        private abstract class LinkedHashIterator<T> implements Iterator<T> {
            Entry<K,V> nextEntry    = header.after;//nextEntry指向头结点的下一个节点,也就是双向链表中的第一个节点
            Entry<K,V> lastReturned = null;

            /**
             * The modCount value that the iterator believes that the backing
             * List should have.  If this expectation is violated, the iterator
             * has detected concurrent modification.
             */
            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;
            }
        }

  • 相关阅读:
    Single Number 解答
    Minimum Size Subarray Sum 解答
    Valid Anagram 解答
    Count Primes 解答
    fullCalendar 日历显示每天数据调用方法实践
    jqGrid列的统计
    关于 asp.net Web Api 上传文件请求内容过大404错误记录
    My97DatePicker只显示月份
    js 宏微任务执行顺序
    git 等官网下载慢方法
  • 原文地址:https://www.cnblogs.com/wanglingdeboke/p/9719677.html
Copyright © 2020-2023  润新知