黑马程序员技术交流社区
标题:
关于List迭代的小问题。
[打印本页]
作者:
wyqs92
时间:
2014-5-18 21:56
标题:
关于List迭代的小问题。
本帖最后由 wyqs92 于 2014-5-19 21:36 编辑
package myreview;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class day18test2 {
public static void main(String[] args) {
/*
* list集合练习
*
*/
List list=new ArrayList();
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
list.add("abc5");
list.add("abc6");
System.out.println("原集合"+list);
for(ListIterator it=list.listIterator();it.hasNext();){
Object obj=new Object();
obj=it.next();
if(obj.equals("abc2")){
it.add("dddd");//为了避免出现并发修改异常,使用了
listIterator() ,但这里为什么不能是list.add("dddd")而是it.add("dddd")了?
}
}
System.out.println(list);
}
}
复制代码
复制代码
作者:
zhrnghgwsws
时间:
2014-5-18 22:22
这种情况下,你要么使用集合的方法,要么使用迭代器的方法。不能同时让集合的方法和迭代器的方法对其进行操作。像你说的会出现并发修改异常。
所以在这个例子中,你在使用迭代器的过程中,要对元素进行操作,就只能使用迭代器的add()方法,即:it.add().
如果使用List.add()就是并发修改异常。
作者:
pandapan
时间:
2014-5-18 22:42
这个是信息同步的问题啦,同学。
1. 迭代器的问题,咱们看看jdk1.6 api怎么描述的吧
public ListIterator<E> listIterator(int index)
返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。指定的索引表示 next 的初始调用所返回的第一个元素。previous 方法的初始调用将返回索引比指定索引少 1 的元素。
此实现返回 ListIterator 接口的直接实现,扩展了由 iterator() 方法返回的 Iterator 接口的实现。ListIterator 实现依赖于底层实现列表的 get(int)、set(int, E)、add(int, E) 和 remove(int) 方法。
注意,除非重写列表的 remove(int)、set(int, E) 和 add(int, E) 方法,否则此实现返回的列表迭代器将抛出 UnsupportedOperationException 来响应其 remove、set 和 add 方法。
根据 (protected) modCount 字段规范中的描述,在面临并发修改时,可以使此实现抛出运行时异常。
复制代码
个人的见解:其实说白了,就是ArrayList内部实现了一个ListIterator接口的一个类,就是说我调用这个方法,就是把ArrayList中所有信息传递给这个子类。
2. 理解了这个之后呢,我们再说为什么使用ListIterator接口可以,使用ArrayList的方法却不行。
其实是迭代器的实现的问题。
一个一个说。
2.1假如说我们使用ArrayList的删除或者增加方法,在此之前呢,我们的ArrayList的数据已经给了ArrayList内部实现了一个ListIterator接口的类,调用这些方法呢,ArrayList内部没有实现通知的机制,即不会去通知已经生成的实现ListIterator接口的类,原因是这样的,假如说实现了通知机制,这是存在问题的,原因如下:
我们知道是、,使用ArrayList是可以删除ArrayList存在的任何元素的,假如我们删除的是在迭代器中已经便利过的,那么即使我们通知迭代器也是无济于事的,因为都已经迭代完了,所以数据时存在问题的。
2.2 为什么我们使用接口的方法就没问题的,因为实现ListIterator接口的类呢,实现了通知的机制,那么你可能会问,这个就不会出现这个问题呢,答案是不会的,我们看看迭代器的api说明,
2.2.1
public void remove()从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。对于每个 next 或 previous 调用,只能执行一次此调用。只有在最后一次调用 next 或 previous 之后,尚未调用 ListIterator.add 时才可以执行该调用。
2.2.2
void add(E e)将指定的元素插入列表(可选操作)。该元素直接插入到 next 返回的下一个元素的前面(如果有),或者 previous 返回的下一个元素之后(如果有);如果列表没有元素,那么新元素就成为列表中的唯一元素。新元素被插入到隐式光标前:不影响对 next 的后续调用,并且对 previous 的后续调用会返回此新元素(此调用把调用 nextIndex 或 previousIndex 所返回的值增加 1)。
add方法本来就是就最后增加元素,所以不可能存在问题。
remove方法操作的都是当前元素(这就是指针的问题啦,对于我们使用的previous,next,iterator都会指向我们的结果),没有涉及到已经遍历的元素,所以是可行的。
以下是小小的一个案例,楼主可以先考虑考虑执行的结果是什么?这个是比较有意思的一道题目,我自己写的,希望能够帮到你.
public class ArrayListTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<String> list = new ArrayList<String>();
list.add("str1");
list.add("str2");
list.add("str3");
list.add("str4");
list.add("str5");
for(ListIterator iterator=list.listIterator();iterator.hasNext();){
System.out.println("for each start");
if(iterator.hasPrevious()){
System.out.println("enter if condition");
System.out.println(iterator.previous());
}
}
System.out.println("over");
}
}
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2