LinkList源码分析

                                                                        LinkList源码分析

           一、

             (1)LinkList是一个双向循环链表,其内部有一个entry类来对它维护。

                            private transient Entry<E>   header = new Entry<E>(null,null,null);

                        在Entry中就包含链表的三个属性,previous、next、element

             (2)具体的Entry类如下:

                  private static class Entry<E>{

                      E element;

                      Entry<E>  next;

                      Entry<E> previous;   

                      Entry(E element, Entry<E> next, Entry<E> previous) {   

                      this.element = element;   

                      this.next = next;   

                      this.previous = previous;   

                     }   

                  }  

                element:当前节点的值

                previous:指向当前节点的前一个节点

                next:指向当前节点的后一个节点

                (这就是双向链表的数据结构)

(3)接下来分析一下  remove方法。


 public E removeFirst() {  

return  remove(header.next);  

   }  

引出

private E  remove(Entry<E> e) { 

if (e == header)   

    throw new NoSuchElementException();   //如果是头结点的话,抛出异常
  
 E result = e.element;                                     //用result把待删除结点的值保存下来
   
e.previous.next = e.next; 

e.next.previous = e.previous; 
  
       e.next = e.previous = null; 
  
       e.element = null;   

size--;   

modCount++;   

       return result;   

   }  

可以看出remove(Entry<E> e)是一个私有方法,所有我们是没法直接去调用此方法

的,该方法就是为LinkedList本身服务的,因为LinkedList是由Entry维护,Entry即我们

所说的节点,删除它的操作很简单,只要把当前节点的前一个节点的next指向当前节点

的下一个节点(e.previous.next = e.next;),然后当前节点的下一个节点的previous

指向当前节点的前一个节点(e.next.previous = e.previous;),最后把当前节点的

next,previous、element置为null,以便GC回收(e.next = e.previous = null;

 e.element = null;)删除操作就完成了,我们从中可以看出他的时间复杂度仅为O(1)

,也就是说删除LinkedList中第一个元素和最后一个元素的时间复杂的仅为O(1),所以他的

操作是非常快的。


(4)删除某个具体的对象


public boolean remove(Object o) {  

 

       if (o==null) {   


           for (Entry<E> e = header.next; e != header; e = e.next) {   


               if (e.element==null) {   


                   remove(e);   


                   return true;   
               }   


           }   


       } else {   


           for (Entry<E> e = header.next; e != header; e = e.next) {   


               if (o.equals(e.element)) {     //先找到e元素的位置,然后调用remove删除


                   remove(e);   


                   return true;   


               }   


           }   


       }   


       return false;   


   }  


发现这方法的内部又调用了一个前面已经分析过的remove(Entry<E> e)方法,

 在这个方法中却多了一个for循环,他要从一个节点开始找,直到找到那个值于传入的

参数值相等,我们可以看出他的时间复杂度就不是我们普遍认为的O(1) 了,而变成了

O(n),之所以这样是LinkedList作为一个通用性的链表结构,由Entry去维护该数据结构,

而不是拿我们直接保存在 LinkedList的值,相当于做了一层包装,所以你要删除某个

值,你还得去找到那个对应的Entry对象


(5)删除某个指定位置元素的方法,跟踪一下entry(index)方法


 private Entry<E> entry(int index) {  
 
      if (index < 0 || index >= size)                            //不符合的index要抛异常

          throw new IndexOutOfBoundsException("Index: "+index+  
 
                                              ", Size: "+size);   

      Entry<E> e = header;                               
 
      if (index < (size >> 1)) {    //index小于size的一半
 
          for (int i = 0; i <= index; i++)                
 
              e = e.next;                                         //e由header依次向(size/2)移动过去

      } else {   

          for (int i = size; i > index; i--)            //e大于(size/2)

              e = e.previous;                             //所以e从最后一个往前移动

      }   

      return e;   

  }  

原来删除某个位置的元素还是这样实现的,为了找到index位置的 Entry元素,它根据

index元素与LinkedList大小的一半(size>>1)做了次比较,如果比size/2小,它就由前往

后找,如果比size/2大,它就从后往前找,并不是我们所想的一味的又前往后找,这样

一来,除去比较所消耗的时间,他的时间复杂度为O(n/2)。


(6)添加的操作就没那么复杂了

 
private Entry<E> addBefore(E e, Entry<E> entry) {  

  Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);   

        newEntry.previous.next = newEntry;   

newEntry.next.previous = newEntry;  
 
size++;   

modCount++;   

return newEntry;   

   }  

 这方法的意思是说,把e对应的节点添加到entry的前面,首先构造newEntry对象,即

新节点,然后是新节点的前一个节点的next指向当前的新节点,当前新节点的下一个元

素的previous也指向新节点.





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值