资讯专栏INFORMATION COLUMN

【java源码一带一路系列】之LinkedHashMap.afterNodeAccess()

levy9527 / 2370人阅读

摘要:如今行至于此,当观赏一方。由于所返回的无执行意义。源码阅读总体门槛相对而言比,毕竟大多数底层都由实现了。比心可通过这篇文章理解创建一个实例过程图工作原理往期线路回顾源码一带一路系列之源码一带一路系列之源码一带一路系列之

本文以jdk1.8中LinkedHashMap.afterNodeAccess()方法为切入点,分析其中难理解、有价值的源码片段(类似源码查看是ctrl+鼠标左键的过程)。观光线路图:afterNodeAccess() --> afterNodeInsertion() --> removeEldestEntry() --> afterNodeRemoval() --> internalWriteEntries() ...

☞ afterNodeAccess()
void afterNodeAccess(Node e) { // move node to last
    LinkedHashMap.Entry last;
    if (accessOrder && (last = tail) != e) {
        LinkedHashMap.Entry p =
            (LinkedHashMap.Entry)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;
    }
}

//////////////////////////////// 涉及变量如下:

/**
 * The head (eldest) of the doubly linked list.
 */
transient LinkedHashMap.Entry head;

/**
 * The tail (youngest) of the doubly linked list.
 */
transient LinkedHashMap.Entry tail;

/**
 * The iteration ordering method for this linked hash map: true
 * for access-order, false for insertion-order.
 *
 * @serial
 */
final boolean accessOrder;

上回在HashMap.afterNodeAccess()中说道,“是为LinkedHashMap留的后路”。如今行至于此,当观赏一方。首先需要了解的是LinkedHashMap相比HashMap多了有序性,由双向链表(before,after)实现。源码出现了一些全局变量:

accessOrder:true:按访问顺序排序(LRU),false:按插入顺序排序

head、tail:存放链表首尾

可见仅有accessOrder为true时,且访问节点不等于尾节点时,该方法才有意义。通过before、after重定向,将新访问节点链接为链表尾节点。

☞ afterNodeInsertion()
void afterNodeInsertion(boolean evict) { // possibly remove eldest
    LinkedHashMap.Entry first;
    if (evict && (first = head) != null && removeEldestEntry(first)) {
        K key = first.key;
        removeNode(hash(key), key, null, false, true);
    }
}

protected boolean removeEldestEntry(Map.Entry eldest) {
    return false;
}

细心的你也花现了吧。afterNodeInsertion()由于removeEldestEntry()所返回的false无执行意义。也就意味着如果想要让它有意义必须重写removeEldestEntry()。

如,使用LinkedHashMap实现一个简单的LRU(Least Recently Used)Cache。那么就应该重写removeEldestEntry(),当超出缓存容器大小时移除最老的首节点(这里不考虑并发问题,如下):

@Override  
public boolean removeEldestEntry(Map.Entry eldest){       
    return size() > capacity;          
}  
☞ afterNodeRemoval()
void afterNodeRemoval(Node e) { // unlink
        LinkedHashMap.Entry p =
            (LinkedHashMap.Entry)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;
    }

afterNodeRemoval()方法相对简单,就是在删除后处理其对应链表前后关系(刨掉一截)。

☞ internalWriteEntries()

LinkedHashMap源码阅读总体门槛相对而言比HashMap,毕竟大多数底层put,get都由HashMap实现了。internalWriteEntries()相对来说比较突兀,如果你知道它在哪里起着什么样神秘的作用请在评论里告诉在下吧。[比心❤]

void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
    for (LinkedHashMap.Entry e = head; e != null; e = e.after) {
        s.writeObject(e.key);
        s.writeObject(e.value);
    }
}

可通过这篇文章理解创建一个LinkedHashMap实例过程(图):

Java_LinkedHashMap工作原理 2017-05-04;

往期线路回顾:

【java源码一带一路系列】之HashMap.putAll()
【java源码一带一路系列】之HashMap.putVal()
【java源码一带一路系列】之HashMap.compute()

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/70089.html

相关文章

  • java源码一带一路系列ArrayList

    摘要:一路至此,风景过半。与虽然名字各异,源码实现基本相同,除了增加了线程安全。同时注意溢出情况处理。同时增加了考虑并发问题。此外,源码中出现了大量泛型如。允许为非线程安全有序。 一路至此,风景过半。ArrayList与Vector虽然名字各异,源码实现基本相同,除了Vector增加了线程安全。所以作者建议我们在不需要线程安全的情况下尽量使用ArrayList。下面看看在ArrayList源...

    RebeccaZhong 评论0 收藏0
  • java源码一带一路系列HashSet、LinkedHashSet、TreeSet

    摘要:同样在源码的与分别见看到老朋友和。这样做可以降低性能消耗的同时,还可以减少序列化字节流的大小,从而减少网络开销框架中。使用了反射来寻找是否声明了这两个方法。十进制和,通过返回值能反应当前状态。 Map篇暂告段落,却并非离我们而去。这不在本篇中你就能经常见到她。HashSet、LinkedHashSet、TreeSet各自基于对应Map实现,各自源码内容较少,因此归纳为一篇。 HashS...

    UCloud 评论0 收藏0
  • java源码一带一路系列HashMap.compute()

    摘要:本篇涉及少许以下简称新特性,请驴友们系好安全带,准备开车。观光线路图是在中新增的一个方法,相对而言较为陌生。其作用是把的计算结果关联到上即返回值作为新。实际上,乃缩写,即二元函数之意类似。 本文以jdk1.8中HashMap.compute()方法为切入点,分析其中难理解、有价值的源码片段(类似源码查看是ctrl+鼠标左键的过程)。本篇涉及少许Java8(以下简称J8)新特性,请驴友们...

    wapeyang 评论0 收藏0
  • java源码一带一路系列HashMap.putAll()

    摘要:观光线路图将涉及到的源码全局变量哈希表初始化长度默认值是负载因子默认表示的填满程度。根据是否为零将原链表拆分成个链表,一部分仍保留在原链表中不需要移动,一部分移动到原索引的新链表中。 前言 本文以jdk1.8中HashMap.putAll()方法为切入点,分析其中难理解、有价值的源码片段(类似ctrl+鼠标左键查看的源码过程)。✈观光线路图:putAll() --> putMapEnt...

    chanjarster 评论0 收藏0
  • java源码一带一路系列HashMap.putVal()

    摘要:表示该类本身不可比表示与对应的之间不可比。当数目满足时,链表将转为红黑树结构,否则继续扩容。至此,插入告一段落。当超出时,哈希表将会即内部数据结构重建至大约两倍。要注意的是使用许多有这相同的键值肯定会降低哈希表性能。 回顾上期✈观光线路图:putAll() --> putMapEntries() --> tableSizeFor() --> resize() --> hash() --...

    cloud 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<