`

读LinkedHashMap源码

阅读更多
//LinkedHashMap继承了HashMap,他和HashMap相比维持了一个插入时候的顺序。LinkedHashMap和HashMap之间也是一种模板设计模式的体现
//先看构造函数
public LinkedHashMap() {
        super();
	//排序规则false按照插入顺序读出,true最近最少使用可用于做LRU(Least Recently Used)缓存
        accessOrder = false;
    }

public LinkedHashMap(int initialCapacity) {
        super(initialCapacity);
        accessOrder = false;
    }

public LinkedHashMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
        accessOrder = false;
    }

 public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
    }

public LinkedHashMap(Map<? extends K, ? extends V> m) {
        super(m);
        accessOrder = false;
    }

//覆盖HashMap中的init钩子方法。
 void init() {
        header = new Entry<>(-1, null, null, null);
        header.before = header.after = header;
    }

//在新增的时候会调用父类的方法
public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
		//这句代码是关键,这也是个钩子方法.执行LinkedHashMap里面的recordAccess方法。
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
	//这句又被覆盖了
        addEntry(hash, key, value, i);
        return null;
    }

  void recordAccess(HashMap<K,V> m) {
            LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
	    //如果是LRU模式
            if (lm.accessOrder) {
                lm.modCount++;
		//删除了自己
                remove();
		//在把自己重新加入队列中,这样headed.after永远都是在队列中最不常用的。
                addBefore(lm.header);
            }
        }

private void remove() {
            before.after = after;
            after.before = before;
        }


//调用remove()的时候会调用这个方法
void recordRemoval(HashMap<K,V> m) {
            remove();
        }

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) {
      1  HashMap.Entry<K,V> old = table[bucketIndex];
      2  Entry<K,V> e = new Entry<>(hash, key, value, old);
      3  table[bucketIndex] = e;
         1,2,3的步骤和HashMap的操作一直
	 
        e.addBefore(header);
        size++;
    }

//这个覆盖了父类在扩容时候的元素迁移
void transfer(HashMap.Entry[] newTable, boolean rehash) {
        int newCapacity = newTable.length;
	//从header双向列表开始迁移比原来的transfer直接从entry[]上更加快,效率更高
        for (Entry<K,V> e = header.after; e != header; e = e.after) {
            if (rehash)
                e.hash = (e.key == null) ? 0 : hash(e.key);
            int index = indexFor(e.hash, newCapacity);
            e.next = newTable[index];
            newTable[index] = e;
        }
    }
//构建了一个双向链表将元素插到了head的前面,head.before的后面,也就是按顺序插入
 private void addBefore(Entry<K,V> existingEntry) {
            after  = existingEntry;
            before = existingEntry.before;
            before.after = this;
            after.before = this;
        }


//获取元素
public V get(Object key) {
        Entry<K,V> e = (Entry<K,V>)getEntry(key);
        if (e == null)
            return null;
        e.recordAccess(this);
        return e.value;
    }

//回到初始状态
 public void clear() {
        super.clear();
        header.before = header.after = header;
    }
 
 //重新覆盖了containsValue方法直接从header开始遍历效率更高
 public boolean containsValue(Object value) {
        // Overridden to take advantage of faster iterator

        if (value==null) {
            for (Entry e = header.after; e != header; e = e.after)
                if (e.value==null)
                    return true;
        } else {
            for (Entry e = header.after; e != header; e = e.after)
                if (value.equals(e.value))
                    return true;
        }
        return false;
    }

//在调用map.entry遍历的时候覆盖了newEntryIterator方法。
Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }

private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {
        public Map.Entry<K,V> next() { return nextEntry(); }
    }

private abstract class LinkedHashIterator<T> implements Iterator<T> {
        Entry<K,V> nextEntry    = header.after;
        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;
        }
       //从head开始挨个遍历这样也就保证了FIFO顺序
        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;
        }
    }



/**
总结:LinkedHashMap继承了HashMap.内部维护了一个双向链表来保证可以按照顺序取出或者按照最少被使用来取出元素。
他的遍历方法直接从内部的双向链表遍历,这样效率更高。
这个类也是模板设计模式的最佳体现。几个钩子方法的使用很精妙。
*/
分享到:
评论

相关推荐

    JavaLinkedHashMap源码解析Java开发Ja

    Java LinkedHashMap 是一个根据插入顺序...通过深入理解 `LinkedHashMap` 的源码,开发者可以更好地优化程序性能,尤其是在处理大量数据和需要特定顺序的场景下。同时,对于提升 Java 开发技巧和经验也是大有裨益的。

    Java集合系列之LinkedHashMap源码分析

    Java集合系列之LinkedHashMap源码分析 Java集合系列之LinkedHashMap源码分析是Java集合框架中的一部分,主要对LinkedHashMap的源码进行了详细的分析。LinkedHashMap是继承自HashMap的,它重新写了一个Entry,在原来...

    Java中LinkedHashMap源码解析

    Java中LinkedHashMap源码解析 LinkedHashMap是Java中的一种哈希表实现,它继承自HashMap,具有可预知的迭代顺序。LinkedHashMap维护着一个运行于所有条目的双重链表结构,该链表定义了迭代顺序,可以是插入或者访问...

    Java集合框架源码分析之LinkedHashMap详解

    Java集合框架源码分析之LinkedHashMap详解 Java集合框架中的LinkedHashMap是HashMap的子类,它继承了HashMap的存储结构,但引入了一个双向链表的头结点,将所有put到LinkedHashMap的节点连接成一个双向循环链表,...

    LinkedHashmap的使用

    **HashMap与LinkedHashMap的区别** HashMap是Java集合框架中的一员,它是基于哈希表实现的,提供了快速的插入、删除和查找操作,平均时间复杂度为O(1)。然而,HashMap不保证元素的顺序,迭代时元素的顺序可能与插入...

    LinkedHashMap

    LinkedHashMap源代码,Java中Map的一种实现子类。

    HashMap,HashTable,LinkedHashMap,TreeMap的区别

    HashMap, HashTable, LinkedHashMap, TreeMap 的区别 在 Java 中,Map 是一个非常重要的集合类,用于存储键值对。其中,HashMap, HashTable, LinkedHashMap, TreeMap 是四种常用的 Map 实现类,每种类都有其特点和...

    java中HashMap,LinkedHashMap,TreeMap,HashTable的区别

    ### Java中HashMap, LinkedHashMap, TreeMap,HashTable的区别 在Java编程语言中,`Map`接口是集合框架中的一个重要组成部分,用于存储键值对。本文将详细分析四种常用的`Map`实现类:`HashMap`, `LinkedHashMap`, ...

    一文搞懂Java的LinkedHashMap.docx

    《深入解析Java的LinkedHashMap》 HashMap作为Java中常用的键值对存储结构,以其高效的查找速度赢得了广大开发者们的青睐。然而,HashMap的无序性在某些特定场景下却显得力不从心,例如当我们需要按照插入顺序来...

    Java集合类源码(摘自jr源码)

    在给定的压缩包文件中,包含了一些关键的集合类源码,如`TreeMap`、`Hashtable`、`ArrayList`、`HashMap`、`LinkedList`、`List`、`Map`、`TreeSet`、`LinkedHashMap`和`Set`。这些类都是Java集合框架的重要组成部分...

    Java集合系列(LinkedHashMap+LinkedList+ArrayList)

    Java 集合系列(LinkedHashMap+LinkedList+ArrayList) Java 集合系列是 Java 语言中的一种数据结构,用于存储和操作数据。今天,我们将介绍 Java 集合系列中的三个重要成员:LinkedHashMap、LinkedList 和 ArrayList...

    java集合-LinkedHashMap的使用

    LinkedHashMap是Java中的一种特殊类型的HashMap,它保留了插入顺序,即按照元素插入的先后顺序进行排序

    java HashMap,TreeMap与LinkedHashMap的详解

    在Java编程语言中,`HashMap`、`TreeMap`和`LinkedHashMap`都是`java.util.Map`接口的实现,它们提供了不同的数据存储和访问策略。本文将深入探讨这三种数据结构的特点、工作原理以及适用场景。 1. **HashMap** `...

    Java使用LinkedHashMap进行分数排序

    Java使用LinkedHashMap进行分数排序 Java中进行分数排序是非常重要的,特别是在学生成绩统计的问题中。传统的排序方法对于排序存在许多相同元素的情况有些浪费,明显即使值相等,两个元素之间也要比较一下,这在...

Global site tag (gtag.js) - Google Analytics