我在书上看到, 如果获得容器对象的迭代器以后,改变了原容器中的数据,之后使用迭代器会失败。所以,在获取迭代器之后,不要对容器做任何修改。
但是我 修改了容量,为什么不报错。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class OperArrayListDemo {
public static void arrayListOne()
{
ArrayList lst=new ArrayList();
lst.add("aa");
lst.add(5);
lst.add("bb");
String a=(String)lst.get(0).toString();
//System.out.println(a);
//displayListOne(lst);
displayListTwo(lst);
lst.add("cc");
displayListOne(lst);
}
public static void displayListOne(List list)
{
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i).toString());
}
}
/*
* 通过迭代器输出
*/
public static void displayListTwo(List list)
{
Iterator iterator=list.listIterator();
while(iterator.hasNext())
{
System.out.println(iterator.next());
}
}
public static void main(String args[])
{
arrayListOne();
}
}
但是我 修改了容量,为什么不报错。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class OperArrayListDemo {
public static void arrayListOne()
{
ArrayList lst=new ArrayList();
lst.add("aa");
lst.add(5);
lst.add("bb");
String a=(String)lst.get(0).toString();
//System.out.println(a);
//displayListOne(lst);
displayListTwo(lst);
lst.add("cc");
displayListOne(lst);
}
public static void displayListOne(List list)
{
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i).toString());
}
}
/*
* 通过迭代器输出
*/
public static void displayListTwo(List list)
{
Iterator iterator=list.listIterator();
while(iterator.hasNext())
{
System.out.println(iterator.next());
}
}
public static void main(String args[])
{
arrayListOne();
}
}
解决方案 »
- 请教个JinternalFrame的问题
- Java要用SQL 2005内bigint型数据,如何获得并转换为String型?
- Jacob 操作Excel的问题???
- 菜鸟问题,(打包安装)
- 缓存可以用内存实现,也可以用文件实现,请问这两者有何区别和联系?
- 设置虚拟目录
- JAVA新手 进程问题
- jbulider6的问题,为什么application server的路径不能改
- 我正准备转如JAVA开发,请问我的电脑里究竟需要装多少东西(如:JBuider、UltranEdit等等)且它们都完成什么功能?---无知的人不可耻,请多帮助。
- 求大神
- 关于java操作word
- java如何读取shapefile
import java.util.List;public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("a");
list.add("a");
list.add("b");
for(String s : list) {
if(s.equals("b")) {
list.add(s);
}
}
}
}个人觉得看一下Java Tutorial上面这方面的介绍很好。
package aa;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class OperArrayListDemo {
public static void arrayListOne()
{
ArrayList lst=new ArrayList();
lst.add("aa");
lst.add(5);
lst.add("bb");
String a=(String)lst.get(0).toString();
//System.out.println(a);
//displayListOne(lst);
Iterator iterator = displayListTwo(lst);
lst.add("cc");
while(iterator.hasNext())
{
System.out.println(iterator.next());
}
displayListOne(lst);
}
public static void displayListOne(List list)
{
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i).toString());
}
}
/*
* 通过迭代器输出
*/
public static Iterator displayListTwo(List list)
{
Iterator iterator=list.listIterator();
return iterator;
}
public static void main(String args[])
{
arrayListOne();
}
}
01.public interface Iterator {
02. boolean hasNext();
03. Object next();
04. void remove();
05.}
public interface Iterator {
boolean hasNext();
Object next();
void remove();
}
每一种集合类返回的Iterator具体类型可能不同,Array可能返回ArrayIterator,Set可能返回SetIterator,Tree 可能返回TreeIterator,但是它们都实现了Iterator接口,因此,客户端不关心到底是哪种Iterator,它只需要获得这个 Iterator接口即可,这就是面向对象的威力。让我们来看看AbstracyList如何创建Iterator。首先AbstractList定义了一个内部类(inner class):
view plaincopy to clipboardprint?
01.private class Itr implements Iterator {
02. ...
03.}
private class Itr implements Iterator {
...
} 而iterator()方法的定义是:view plaincopy to clipboardprint?
01.public Iterator iterator() {
02. return new Itr();
03.}
public Iterator iterator() {
return new Itr();
}
因此客户端不知道它通过Iterator it = a.iterator();所获得的Iterator的真正类型。现在我们关心的是这个申明为private的Itr类是如何实现遍历AbstractList的:view plaincopy to clipboardprint?
01.private class Itr implements Iterator {
02. int cursor = 0;
03. int lastRet = -1;
04. int expectedModCount = modCount;
05.}
private class Itr implements Iterator {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
}
Itr类依靠3个int变量(还有一个隐含的AbstractList的引用)来实现遍历,cursor是下一次next()调用时元素的位置,第一次调用next()将返回索引为0的元素。lastRet记录上一次游标所在位置,因此它总是比cursor少1。变量cursor和集合的元素个数决定hasNext():view plaincopy to clipboardprint?
01.public boolean hasNext() {
02. return cursor != size();
03.}
public boolean hasNext() {
return cursor != size();
} 方法next()返回的是索引为cursor的元素,然后修改cursor和lastRet的值:view plaincopy to clipboardprint?
01.public Object next() {
02. checkForComodification();
03. try {
04. Object next = get(cursor);
05. lastRet = cursor++;
06. return next;
07. } catch(IndexOutOfBoundsException e) {
08. checkForComodification();
09. throw new NoSuchElementException();
10. }
11.}
public Object next() {
checkForComodification();
try {
Object next = get(cursor);
lastRet = cursor++;
return next;
} catch(IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
expectedModCount表示期待的modCount值,用来判断在遍历过程中集合是否被修改过。AbstractList包含一个 modCount变量,它的初始值是0,当集合每被修改一次时(调用add,remove等方法),modCount加1。因此,modCount如果不变,表示集合内容未被修改。Itr初始化时用expectedModCount记录集合的modCount变量,此后在必要的地方它会检测modCount的值:view plaincopy to clipboardprint?
01.final void checkForComodification() {
02. if (modCount != expectedModCount)
03. throw new ConcurrentModificationException();
04.}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
如果modCount与一开始记录在expectedModeCount中的值不等,说明集合内容被修改过,此时会抛出ConcurrentModificationException。这个ConcurrentModificationException是RuntimeException,不要在客户端捕获它。如果发生此异常,说明程序代码的编写有问题,应该仔细检查代码而不是在catch中忽略它。但是调用Iterator自身的remove()方法删除当前元素是完全没有问题的,因为在这个方法中会自动同步expectedModCount和modCount的值:view plaincopy to clipboardprint?
01.public void remove() {
02. ...
03. AbstractList.this.remove(lastRet);
04. ...
05. // 在调用了集合的remove()方法之后重新设置了expectedModCount:
06. expectedModCount = modCount;
07. ...
08.}
public void remove() {
...
AbstractList.this.remove(lastRet);
...
// 在调用了集合的remove()方法之后重新设置了expectedModCount:
expectedModCount = modCount;
...
}
要确保遍历过程顺利完成,必须保证遍历过程中不更改集合的内容(Iterator的remove()方法除外),因此,确保遍历可靠的原则是只在一个线程中使用这个集合,或者在多线程中对遍历代码进行同步。
http://blog.csdn.net/aj_zLc/archive/2010/10/30/5976202.aspx