关于三种方式的效率可以直接看下面的测试代码,遍历1000条数据分别用的时间。
package com.jettyw.arraylist;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ArrayListM {
private static List list=new ArrayList();
public static void addList(){
for(int i=0;i<1000;i++){
list.add("测试"+i);
}
}
public static void ergodicTest1(){
long startTime=System.currentTimeMillis();
for(int i=0;i
System.out.print(list.get(i));
}
System.out.println();
long endTime=System.currentTimeMillis();
System.out.println("花费时间为1:"+(endTime-startTime));
}
public static void ergodicTest2(){
long startTime=System.currentTimeMillis();
for(String str:list){
System.out.print(str);
}
System.out.println();
long endTime=System.currentTimeMillis();
System.out.println("花费时间为2:"+(endTime-startTime));
}
public static void ergodicTest3(){
long startTime=System.currentTimeMillis();
Iteratoritr=list.iterator();
while(itr.hasNext()){
System.out.print(itr.next());
}
long endTime=System.currentTimeMillis();
System.out.println();
System.out.println("花费时间为3:"+(endTime-startTime));
}
public static void main(String[] args) {
addList();
ergodicTest1();
ergodicTest2();
ergodicTest3();
}
}
上面测试结果为
花费时间为1:16
花费时间为2:9
花费时间为3:4
可以看出来使用Iterator遍历效率最高。
Iterator遍历采用了一种fail-fast机制。什么是fail-fast机制呢,从字面意思就是快速失败的意思,从安全角度来讲,Iterator尽可能的抛出可能失败的异常。我们前面的源码都有modCount++,最开始我也没有介绍,它是实现fail-fast机制的关键。 从中,我们发现:无论是add()、remove(),还是clear(),只要涉及到修改集合中的元素个数时,都会改变modCount的值。
当多个线程对同一个集合进行操作的时候,某线程访问集合的过程中,该集合的内容被其他线程所改变(即其它线程通过add、remove、clear等方法,改变了modCount的值);这时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。
在Iterator的操作中,Itr类初始化时int expectedModCount = modCount;并且在next(),remove()方法中都有checkForComodification();用于检测expectedModCount 与modCount是否相等,如果不相同则说明list发生修改,立即返回异常,而不是遍历到应该返回异常的地方返回异常。
我们可以看一个产生fail-fast的案例
package com.jettyw.arraylist;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class FailFastTest {
private static List list = new ArrayList<>();
//线程1遍历元素
private static class threadOne extends Thread{
public void run() {
Iterator iterator = list.iterator();
while(iterator.hasNext()){
//由于使用fial-fast机制,直接抛出异常
int i = iterator.next();
System.out.println("ThreadOne 遍历:" + i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//线程二删除一个元素
private static class threadTwo extends Thread{
public void run(){
int i = 0 ;
while(i < 6){
System.out.println("ThreadTwo run:" + i);
if(i == 3){
list.remove(i);
}
i++;
}
}
}
public static void main(String[] args) {
for(int i = 0 ; i < 10;i++){
list.add(i);
}
new threadOne().start();
new threadTwo().start();
}
}
我们由此也看出了ArrayList在多线程中的一些问题,下章节,我们对这些问题进行总结。