Java8LinkedHahMap解析

本博客是基于Java8的,预期是想将所有函数都看一遍:

	这是查看source时候的第一个代码块:是一个构造函数
    private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
    	//保存之前的链尾
        LinkedHashMap.Entry<K,V> last = tail;
        //将参数值赋值给链尾,此时last还是指向原先的链尾
        //有个疑问:为什么要进行赋值,而不是直接采用下面自己写的方式
        //原因在于:Java存取堆栈中的数据比存取成员变量和全局变量的操作要少,因而性能更高
        tail = p;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
        //自己写的  
        if(tail==null){
			head=p;
		}else{
			p.before=tail;
			tail.after=p;
		}
    }

第二个代码块:

    // 将src node连接至dst末尾
    private void transferLinks(LinkedHashMap.Entry<K,V> src,
                               LinkedHashMap.Entry<K,V> dst) {
        LinkedHashMap.Entry<K,V> b = dst.before = src.before;
        LinkedHashMap.Entry<K,V> a = dst.after = src.after;
		//确保无论是src或者dst都有前节点,意味着如果不为空,说明这个节点是挂在某个串下的,则继续讲这个节点挂在这个串下
        if (b == null)
            head = dst;
        else
            b.after = dst;
        //判断无论是src或者是ds是否后面还连着一个串,如果连着则继续连着
        if (a == null)
            tail = dst;
        else
            a.before = dst;
            //这种编码形式很棒啊,不采用if判断,而是直接连等代替
    }

之后的是一些静态内部类的构造函数,跳过
替换节点函数:

    Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {
    	//父类想向转为子类
        LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p;
        LinkedHashMap.Entry<K,V> t =
            new LinkedHashMap.Entry<K,V>(q.hash, q.key, q.value, next);
            //相连
        transferLinks(q, t);
        return t;
    }

节点移除函数

   void afterNodeRemoval(Node<K,V> e) { // unlink
        LinkedHashMap.Entry<K,V> p =
            (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
            //将这个节点的前驱节点和后驱节点都设为空
        p.before = p.after = null;
        //没有前驱节点,说明这个节点不是挂在某个串上的,说明是头节点,则将head指向头结点的下一个节点
        if (b == null)
            head = a;
        else
        //指向下一个节点,防止断链
            b.after = a;
        if (a == null)
        //说明是尾节点,则将尾节点指向前一个节点
            tail = b;
        else
        //否则相连
            a.before = b;
    }

判断入队之后是否需要出队:


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

2018-10-10 23:13 更:
LinkedHashMap与HashMap的区别在于LinkedHashMap是一个双向链表,看源码的时候有点奇怪,put的时候并没有看到如何维护的啊,head,tail哪里用到了,后来发现原来是重写了:newNode方法:

	这个方法将tail节点和新增的节点拉钩,,这样就维护好了一个双向队列
    Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
        LinkedHashMap.Entry<K,V> p =
            new LinkedHashMap.Entry<K,V>(hash, key, value, e);
        linkNodeLast(p);
        return p;
    }
     private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
        LinkedHashMap.Entry<K,V> last = tail;
        tail = p;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
    }

借用一下别人的图,有这张图大家应该瞬间明了了:
结构图
此图转自:https://blog.csdn.net/u012403290/article/details/70143443?locationNum=14&fps=1 尊重原创。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值