LinkedHashMap原理分析

来源:互联网 发布:全国心智障碍者数据 编辑:程序博客网 时间:2024/04/27 20:49

LinkedHashMap原理分析

一.实现

LinkedHashMap继承HashMap数据结构:HashMapEntry(key,value)--》LinkedHashMapEntry(key,value+before指针和after指针(双向链表))1.构造函数LinkedHashMap/*    accessOrder true if the ordering should be done based on the last access (from least-recently accessed to most-recently     accessed), and false if the ordering should be the order in which the entries were inserted.*/public LinkedHashMap(        int initialCapacity, float loadFactor, boolean accessOrder) {    super(initialCapacity, loadFactor);    init();    this.accessOrder = accessOrder;}super(initialCapacity, loadFactor) {    // 新建一个HashMap-->创建HashMap对应的集合    ...}@Override void init() {    header = new LinkedEntry<K, V>();}/*    LinkedEntry是双向链表+HashMap的item    LinkedEntry是HashMapEntry的子类    HashMapEntry是HashMap的item*/static class LinkedEntry<K, V> extends HashMapEntry<K, V> {    LinkedEntry<K, V> nxt;    LinkedEntry<K, V> prv;    /** Create the header entry */    LinkedEntry() {        super(null, null, 0, null);        nxt = prv = this;    }    /** Create a normal entry */    LinkedEntry(K key, V value, int hash, HashMapEntry<K, V> next,        LinkedEntry<K, V> nxt, LinkedEntry<K, V> prv) {        super(key, value, hash, next);// 调用HashMap的构造函数        this.nxt = nxt;        this.prv = prv;    }}2.put函数--同HashMap的put函数// 覆写该函数// 修改已经put进去的key对应的value的时候会调用该函数@Override void preModify(HashMapEntry<K, V> e) {    if (accessOrder) {        makeTail((LinkedEntry<K, V>) e);    }}// 将e元素插入到循环双向链表的末尾(如果之前已经插入到循环双向链表中,则删除,然后插入到末尾)/*** Relinks the given entry to the tail of the list. Under access ordering,* this method is invoked whenever the value of a  pre-existing entry is* read by Map.get or modified by Map.put.*/private void makeTail(LinkedEntry<K, V> e) {// Tail:尾巴    // Unlink e    e.prv.nxt = e.nxt;    e.nxt.prv = e.prv;    // header是LinkedEntry的链表,LinkedEntry在1构造函数中有介绍    // Relink e as tail    LinkedEntry<K, V> header = this.header;    // 将e插入到循环双向链表的最后一个元素    LinkedEntry<K, V> oldTail = header.prv;    e.nxt = header;    e.prv = oldTail;    oldTail.nxt = header.prv = e;    modCount++;}// 覆写该函数--相当于调用makeTail,把item插入到双向队列的末尾@Override void addNewEntry(K key, V value, int hash, int index) {    LinkedEntry<K, V> header = this.header;    // Remove eldest entry if instructed to do so.    LinkedEntry<K, V> eldest = header.nxt;    if (eldest != header && removeEldestEntry(eldest)) {        remove(eldest.key);    }    // Create new entry, link it on to list, and put it into table    LinkedEntry<K, V> oldTail = header.prv;    LinkedEntry<K, V> newTail = new LinkedEntry<K,V>(key, value, hash, table[index], header, oldTail);    table[index] = oldTail.nxt = header.prv = newTail;}3.get函数// 该实现和HashMap的get函数实现几乎一样,除了注释的那句代码外@Override public V get(Object key) {    ...    // Replace with Collections.secondaryHash when the VM is fast enough (http://b/8290590).    int hash = secondaryHash(key);    HashMapEntry<K, V>[] tab = table; // HashMap.java的table    for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];            e != null; e = e.next) {        K eKey = e.key;        if (eKey == key || (e.hash == hash && key.equals(eKey))) {            if (accessOrder) // 添加的代码.如果是按照Lru算法实现,这重新调整该item在循环双向链表中的位置                makeTail((LinkedEntry<K, V>) e);            return e.value;        }    }    return null;}4.remove函数--同HashMap的remove函数// 覆写通知函数// 将该item从双向循环链表中删除@Override void postRemove(HashMapEntry<K, V> e) {    LinkedEntry<K, V> le = (LinkedEntry<K, V>) e;    le.prv.nxt = le.nxt;    le.nxt.prv = le.prv;    le.nxt = le.prv = null; // Help the GC (for performance)}

二.总结

1.要了解LinedHashMap的实现,要先知道他的父类HashMap的实现,LinkedHashMap的大部分实现都在他父类中实现2.当开启Lru算法的时候(accessOrder参数设置为true),LinkedHashMap比HashMap多的是该类自己维护双向循环链表,当增删改的时候会修改该链表,把最新的item放到末尾(Tail)3.本质:LinkedHashMap == HashMap + LinkedList
原创粉丝点击