LinkedList的源码学习 再次继续,现在看add(int,E),这个方法是在指定位置插入元素,索引位起始是0
因为指定位置插入,需要遍历链表,所以时间复杂度为O(n)
写上测试代码,并且附上运行结果
点击dbug,点击下一步。 这里先检查索引位是否合法。
再次点击下一步。进入checkPositionIndex(),但是检查索引位是否合法,却是isPositionIndex()
再次点击下一步,这里的index必须比0 大 并且比size小,也就是说,可以插在第一个位置和 链表的末尾(也就是作为链表的最后一个元素),或者是在他们的中间。
再次点击下一步。这里开始进行逻辑判断,如果index==size 。说明是把这个节点附在链表的尾巴上,也就是末尾
linkLast()这个方法,之前已经看了。这里跳过
再次点击下一步,这里有和linkBefore()方法,还有个node()函数
再次点击下一步,进入node()方法。在node()方法里面,为了保证查找的效率,先对链表长度进行 除2.
然后在把除2后的值 跟index 这个索引比较,这样是为了提高查找效率。然后再遍历另外一半就行了。这个算法比较简单。
再次点击下一步。这里将 要插入的元素和 索引对应的节点传进linkBefore()方法
点击下一步,这里我们需要把这个索引位的节点的前一个节点的引用交给 pred变量保存。为什么要这样呢?因为我们需要在succ节点前插入新的节点,同时这还是一个双向链表,所以,我们得先保存下 succ节点的前一个节点的引用。
再次点击下一步,这里开始创建一个节点,这个新节点的前置节点是succ的前一个节点,后置节点是succ节点。这里我们把这个新创建的节点的引用也交给变量newNode保存。
点击下一步。
再次点击下一步,因为是双向链表,所以,我们这里也需要把newNode的引用给 succ.prev 也就是让succ指向这个新节点,双向链表
再次点击下一步。这里会判断,是否我们插入的是第一个位置,因为pred是succ的前置节点,如果succ是第一个节点,那么他的前置节点就是null。如果是null,说明我们要插入的是第一个节点,那么直接把头指针指向新节点就行了,这里这个判断肯定是false,我们继续点击下一步
点击下一步。这里就把pred的指向newNode,这个新节点就行了。
经过了这一系列操作,我们就把新节点和它前面,后面的节点 互相指向了,如此 就把这个节点添加到了这个双向链表中,那么最后size++,modcount++ ,就ok
好了,到这里,又学习完了一个 add()方法,后续将会继续学习 另外两个addAll()方法。
如果博客有什么问题请指出,大家一起学习进步。