[置顶] 有关ListIterator接口的add与remove方法探究

时间:2021-06-03 05:25:01

ListIterator接口继承自Iterator接口,新增了add()等方法。

关于ListIterator的add()方法的作用(接口是没有方法实现的,但其实现类对于add()方法的实现机制大致相同,姑且这样说吧),《java核心技术 卷I》里如下表述:

“如果多次调用add方法,将按照提供的次序把元素添加到链表中。它们被依次添加到迭代器当前位置之前。”

对于这种说法,很容易引发歧义,当前位置是什么?当前指向的元素,还是游标位置?

带着这种疑问,我查阅了ListIterator接口的API说明文档(网址见本文结尾),得到对于add()方法的如下英文描述:

Inserts the specified element into the list (optional operation). The element is inserted immediately before the element that would be returned bynext(), if any, and after the element that would be returned by previous(), if any. (If the list contains no elements, the new element becomes the sole element on the list.)

该描述就很清晰:的确是把新元素插入由next()所返回的那个元素之前,previous()所返回的元素之后。之所以加之前与之后两个限定,是为了应对在链尾(next返回为空)以及链头(previous返回为空)的特殊情况,如果链表为空,则新插入的元素就作为该链表的唯一元素。另外,每当插入一个元素以后,迭代器都会后移(向着链尾方向)一位。

举例说明:

List<String> name=new LinkedList<String>();
name.add("A");
name.add("B");
name.add("C");
ListIterator<String> iter = name.listIterator();
iter.next();
iter.add("D");
iter.add("E");
for(String nm:name)
System.out.println(nm);

第4行代码执行完毕,name链表内容如下1A2B3C4(数字只作为占位符,可以忽略,内容为ABC,从链头到链尾)

第5行定义迭代器以后,初始迭代器的位置是在数字1,执行第6行next以后,迭代器指向数字2的位置,此时如果再执行next(),返回B,执行previous(),返回A,因此应把D插入AB之间,迭代器顺移到DB之间;依次类推,可以插入E。最终输出结果为:

A
D
E
B
C

下面再简单看一下remove方法,关于remove方法,API文档描述如下:

Removes from the list the last element that was returned bynext() orprevious() (optional operation). This call can only be made once per call to next orprevious. It can be made only ifadd(java.lang.Object) has not been called after the last call to next or previous.

简单解释一下,要执行remove,首先要找到所需移除的元素,怎样找?当然是通过next()跟previous()方法,所以remove必须要跟在next()或是previous()之后,而且只能执行一次(一个元素当然只能删一次,删多个元素,需要再执行next()或previous())。另外,在执行next()或previous()后还不能先执行了 add()方法。因为,否则add()方法执行以后,迭代器已经移动了,这样所要删除的目标元素指向不明,会报”Unknown Source“异常。

所以《java核心技术 卷I》对add和remove方法总结如下:add方法只依赖迭代器的位置(next和previous各返回什么元素),而remove方法依赖于迭代器的状态(是否执行了next或remove方法)。(红色是我的备注)

对于java API文档,推荐GrepCode,网址如下:

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/ListIterator.java?av=h#ListIterator

这里你能看到类或接口的继承以及实现结构,同时还能查看实现源码,很不错。