1、迭代器原理
java 中提供了很多的集合类,不同集合类的数据结构不同,所以这些集合类的数据存储方式和遍历方式也应该不同,所以无法为所有集合类提供统一迭代器,只能提供一个接口。
通过源码分析可以得知,集合对接口的实现在他们的具体实现类中,并且以私有内部类的方式体现。
2、ConcurrentModificationException
public class ConcurrentModificationExceptionDemo
{
public static void main(String[] args)
{
Collection<String> c = new ArrayList<String>();
c.add("Java");
c.add("Android");
c.add("HTML");
c.add("C#");
// 迭代器遍历集合
Iterator<String> it = c.iterator();
while(it.hasNext())
{
String str = it.next();
if(str.equals("Java"))
{
// 集合 add() 方法添加元素
c.add("JavaEE");
}
}
}
}
在运行以上代码时,程序将会抛出 ConcurrentModificationException 异常(并发操作异常),这是因为代码中使用迭代器遍历集合过程中通过集合添加了元素
(1) 概述
当检测到对象的并发修改,但不允许这种修改时抛出该异常
(2) 产生原因
迭代器依赖于集合存在,在迭代时通过集合添加元素,但集合的改变并没有同步到迭代器,所以引发该异常。
(3) 解决方法
方式一:使用迭代器遍历,通过迭代器来修改元素(只使用于 List 实现类)
public class ConcurrentModificationExceptionDemo
{
public static void main(String[] args)
{
List<String> c = new ArrayList<String>();
c.add("Java");
c.add("Android");
c.add("HTML");
c.add("C#");
// 使用迭代器遍历集合
ListIterator<String> it = c.listIterator();
while(it.hasNext())
{
String str = it.next();
if(str.equals("Java"))
{
// 使用迭代器的 add() 添加元素
it.add("JavaEE");
}
}
System.out.println(c);
}
}
运行结果:
方式二: 使用集合遍历,通过集合来修改元素
public class ConcurrentModificationExceptionDemo
{
public static void main(String[] args)
{
List<String> c = new ArrayList<String>();
c.add("Java");
c.add("Android");
c.add("HTML");
c.add("C#");
// 使用集合遍历
for(int i = 0; i < c.size(); i++)
{
String str = c.get(i);
if(str.equals("Java"))
{
// 使用集合 add() 方法添加元素
c.add("JavaEE");
}
}
System.out.println(c);
}
}
运行结果:
注意:
foreach 遍历其底层为迭代器,所以遍历时修改也会出现该异常。
两种方式虽然都满足了需求,但是存在一些不同之处:方式一插入新元素的位置在当前迭代位置的后面;而方式二插入新元素的位置在列表最后面。