【数据结构】2.java源码关于LinkedList
关于LinkedList的源码关注点
? 1.从底层数据结构,扩容策略构造函数不做任何操作,只要再add的时候进行数据初始化操作,以操作推动逻辑,而且linkedlist是一个双向链表,所以可以向前向后双向遍历 ? ?
? ?2.LinkedList的增删改查?2.1 add操作,linklast? Add操作的实质就是进行linklast操作 linklast的操作就是再最后吧节点添加到尾部,并修正size大小 ? ? ? public boolean add(E ele) { linkLast(ele); return true; } ? 我们看看如果是在指定的位置插入元素的操作 ?先看看node定位操作 ? ? ?然后我们看看linkbefore,前置插入 ? public void linkBefore(E e,Node<E> succ) { final Node<E> pred = succ.prev; final Node<E> newNode = new Node<>(pred,e,succ); succ.prev = newNode; if (pred == null) first = newNode; else pred.next = newNode; size++; modCount++; } 那么我们需要插入到指定的位置的方法就可以很简单的实现了 ? 2.2 删除? 查看源码,比较remove(),remove(object),remove(index)等等操作,归根到底还是一个unlink操作 ? ? public E unlink(Node<E> node) { // assert x != null; //这里需要操作的就是三个节点,前置节点,当前节点,后置节点 final E element = node.item; final Node<E> prev = node.prev; final Node<E> next = node.next; //当前节点的前一个节点指向当前节点的下一个节点,说白了node.pre.next = node.next; if (prev == null) { //避免首节点操作 first = next; } else { prev.next = next; node.prev = null; //断开原始连接 } //当前节点的下一个节点的前置节点指向当前节点的上一个节点:node.next.pre = node.pre; if (next == null) { last = prev; } else { next.prev = prev; node.next = null; } //清除当前节点 node.item = null; size--; modCount++; return element; } 其余操作基本就是调用unlink方法进行操作 ? ?修改set和获取get就不多说了,就注意一点就是set操作的时候,会返回旧值,并且这两个操作不会修改modCount值,也就是不会产生链表变动 ? ?3.特殊处理重点关注,iterator,序列化? ? 对于iterator这个就不多说了,其实还是调用上面的那些方法,遍历也就是next和pre和循环遍历没差别
进行序列化、反序列化时,虚拟机会首先试图调用对象里的writeObject和readObject方法,进行用户自定义的序列化和反序列化。如果没有这样的方法,那么默认调用的是ObjectOutputStream的defaultWriteObject以及ObjectInputStream的defaultReadObject方法。换言之,利用自定义的writeObject方法和readObject方法,用户可以自己控制序列化和反序列化的过程。 ? ? 4.遍历的速度,随机访问和iterator访问效率对比这个问题其实也可以舍弃掉了,这里遍历的实质还是使用链表的遍历方式进行遍历 ? ? 5.是否支持多线程LinkedList 是线程不安全的,允许元素为null的双向链表。 ? (编辑:ASP站长网) |