(注意:本文基于JDK1.8)
无论是LinkedList,还是ArrayList,都实现了List接口,List接口表示作为线性表的能力,所以LinkedList和ArrayList提供的API是一致的,只是ArrayList与LinkedList对于List接口的实现是不同的!今天我们继续学习LInkedList修改元素的源码,一个定义在LinkedList类中的set()方法,另一个是定义在迭代器类ListItr中的set()方法,它们都能完成修改元素工作!
set()方法分析
位于LinkedList中的set()方法,用于替换指定下标的元素,第一个参数index表示元素的索引位置,第二个参数element表示替换后的元素对象
public E set(int index, E element) {
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}
set()方法本身覆盖的是LinkedList的父类AbstractSequentialList的set()方法,接下来一起分析一下
1、检查传入下标是否合法
由checkElementIndex()方法检查下标是否符合范围,在LinkedList中只要是使用传入下标的代码,都会做下标范围的检查,这是其中1处。举个例子:现在LinkedList一共持有5个元素,那么下标index的合法范围是0-4,如果index小于0或者大于4都不符合要求
2、获取表示结点的对象
我们向LinedList添加的元素对象,都是由Node对象持有的实例变量item负责保存的,此处通过node()方法获取对应下标的Node对象,目的是为了修改当前Node对象持有的item,修改item指向的对象
3、提取保存的旧元素对象
在第二步中已经获取到对应index的Node对象,此时取出此Node对象持有的item,也就是Node对象持有的旧元素对象,由局部变量oldVal负责保存
4、正式添加新的元素替换掉旧的元素
只要为Node对象x持有的item赋值为指向新的元素对象即可
5、返回被替换的元素对象
return语句直接返回旧的元素对象
set()方法分析(ListItr)
public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.item = e;
}
此set()方法定义在迭代器类ListItr中,重写的是ListIterator接口中定义的方法。此方法只接受传入一个参数,表示即将要替换成的元素对象,我们下面分步学习一下
1、检查迭代器遍历的元素情况
lastReturned是ListItr对象持有的一个实例变量,表示最后一次遍历过的元素,理论上lastReturned为null,则说明几个可能,第一个是创建了迭代器还没有使用过迭代器执行过遍历,lastReturned的初始值为null,第二个是使用迭代器添加了一次元素,此时lastReturned也会为null,表示上一次并没有返回元素,第三个是使用迭代器删除了一次元素,此时lastReturned也会为null,同样表示迭代器上一次没有返回元素,而是进行了删除元素的行为。如果你在lastReturned为null的情况下,执行要修改元素,作者会给你提示,一个IllegalStateException()给你……
2、检查多线程下修改元素
LinedList不支持多线程下操作元素,这里检查也就是说防止你在多线程下使用LinkedList
3、通过检查后替换最后一次遍历过的元素对象
替换最后一次访问过的元素为传入的新元素,完成替换工作
总结
1、node()方法、checkElementIndex()方法都是在LinkedList中多次使用的, 其他篇文章已经介绍,本篇不再提及
2、迭代器ListItr中的set()方法只能替换最后一次通过迭代器访问过的元素
3、LinedList中的set()方法,只要指定的元素下标符合要求,即可完成替换操作