JAVA--LinkedList底层双链表底层源码CRUD分析
集合里面存储的都是对象
1.添加元素/对象
添加第一个元素
添加第二个元素
依次往后添加对象/元素。
pre指针,next指针,first指针,last指针
first指针指向linkedList集合里存储的第一个结点对象,last指针则指向最后一个结点对象,里面如果有一个就同时指向
一个结点对象有(pre,e或者item,next)
pre(或者prev一个意思):指向上一个结点对象,next指向下一个结点对象,node结点(pre,e或者item,next),里面的e或者item是真正存储对象的地方
创建一个LinkedList linkedList = new LinkedList();创建一个实例化集合,此时这个集合里面为空,它的头指针first,和尾指针last都指向null(空),linkList.add("a");
添加一个对象,通过add()方法里面的lastList()方法添加这个对象,进入后现先把尾指针last赋给l,然后创建一个newNode结点对象,
把l赋值给这个这个结点对象的pre,把需要存储的对象存放在这个结点对象的e里面,next再创这个结点对象时里面的方法已经置为null。然后把尾指针last指向新创建的结点对象,
然后判断l是否为空,如果为空,就把头指针指向这个结点,此时l为空所以不走else,此时第一个对象添加完成,添加第二对象时,由于头指针first和尾指针last都指向了
第一个结点对象,在添加第二个对象时,依旧通过add()方法里面的lastList()方法添加这个对象,进入后现先把尾指针last赋给l,所以此时l就指向上一个结点对象(也就是第一个结点对象),
然后创建一个新的结点对象newNode(也就是第二个结点对象),然后将l付给了第二个结点对象的pre,也就说这个时候这个对象的pre就指向了上一个结点对象,
然后把存储的对象存放在这个结点对象的e里面,next依旧为空,然后把尾指针指向这个新创建的节点对象,然后判断l是否为空,此时不为空,所以l.next = newNode;,因为前面l是指向上一个结点,
所以l.next就是上一个结点对象指向下一个节点对象,也就指向了刚才新创建的节点对象(此时为第二个节点对象),所以这个时候双向链表也就构成了。如果往后加对象/元素同时。
2.1删除第一个结点对象
linkedList.removeFirst();
第一步,先让f拥有和头指针first相同的指向,即都指向第一个节点对象。然后判断是否为空,就是不让你删除一个空的集合里面的元素,如果为空就抛出异常
一个结点对象有(pre,e或者item,next)
pre指针指向上一个结点对象,next指向下一个结点对象,node结点(pre,e,next),里面的e或者item是真正存储对象的地方
第二步调用unlinkFirst()方法
先f.item获得你存储的对象赋给element,f.next获得你第一个节点对象的下一个结点对象的指向并赋给next,这样next就指向了第二个结点对象
然后f.item=null把第一个结点对象存储的东西置为null, f.next=null也把第一个结点对象指向第二个节点对象的指针置为null,然后判断next(前面next已经指向第二个结点对象)
是否为null,此时不为null,所以把第二个结点对象的指向上一个结点对象的指针prev置为null,这样第一个结点对象就彻底分离。size--就是集合里面的元素减一
2.1删除某一个结点对象
1.首先判断这个对象的索引是否再这个集合内,不在就抛出异常
2.通过二分查找法找到索引指向的对象结点(和下面的修改和查找元素一样)
3.unlink()删除这个结点对象 【可以画图对着看,有点绕】
至此,要删除的这个结点对象就彻底与集合分离接着
然后删除完成
3.修改或得到元素/对象(JDK1.8用的是二分查找,)
先判断这个索引是不是在这个集合范围内,index >= 0 && index < size,如果不在就抛出异常,如果在就用二分查找
JDK1.8用的是二分查找,如果(索引)index<(size>>1),就从first指向的第一个结点对象往后遍历查找,
如果大于就从last指向的最后一个结点对象往前遍历查找,直到找到索引所在的结点对象。如果修改的化就把需要的值element
赋给找到的结点对象(x)的item【x.item = element;】,然后返回未修改时的那个值。如果是得到这个对象就返回x.item