Iterator 主要性能开销在next方法体,其一:对记录集进行检测,如果在迭代的过程中,记录集有被修改,会抛出异常;其二:next方法体内有try...catch方法体,这也会影响性能,JVM不能对try...catch块内的代码进行优化。
而for因为不管数据被中途修改,也不进行异常处理,所以当然快啦
详细:
ArrayList的iterator是在AbstractList里面的
它的next方法如下:
Java code
public E next() {
checkForComodification();
try {
E next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
而其中的get为:
Java code
public E get(int index) {
rangeCheck(index);
checkForComodification();
return l.get(index+offset);
}
看到这个l.get(index+offset)了没?这个l就是AbstractList本身
所以,最终调用的是ArrayList的get:
Java code
public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
}
总结:对ArrayList而言,for里面的get比较单纯,而iterator的next多了checkForComodification,rangeCheck等,所以变慢了。
引用 5 楼 quqiujie 的回复:
把arrayList改为LinkedList,就知道结果了
LinkedList又是另外一个话题了,不过LZ的程序千万别不动脑筋的把ArrayList变成LinkedList呀。
LZ的程序的for循环,如果用LinkedList的话,慢死你没商量!
理由很简单LinkedList的get(int index)是调用AbstractSequentialList的public E get(int index):
Java code
public E get(int index) {
try {
return listIterator(index).next();
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
而listIterator(index)的最终是要调LinkedList的ListItr(int index):
Java code
ListItr(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
if (index < (size >> 1)) {
next = header.next;
for (nextIndex=0; nextIndex<index; nextIndex++)
next = next.next;
} else {
next = header;
for (nextIndex=size; nextIndex>index; nextIndex--)
next = next.previous;
}
}
现在,知道有多慢了吧?一个for循环,从0知道到index,也就是说LZ的程序如果用LinkedList做for循环调get(int index)方法的话,算法复杂度为O(n*n)!
然而,LinkedList的Iterator却是个好东西。它的next为:
Java code
public E next() {
checkForComodification();
if (nextIndex == size)
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.element;
}
简单吧?就一个next = next.next,全搞定!链表就是这个好,顺序遍历的时候很快,其实我觉得要比上面那个ArrayList的get(return elementData[index])要快。C里面也许数组挺快,但是Java里面,这个elementData是个Object数组,要求offset应该不是就一个乘法加一个加法那么简单吧?就算是一个乘法加一个加法,链表LinkedList就一个next的赋值(next是Entry)应该更快。
Iterator为什么产生?
ArrayList 和 LinkedList 是两个区别很大的集合, 没必要一起比嘛
Iterator 是集合提供的一个通用接口, 用来遍历集合元素的。在Collection下的集合都可以使用这个接口来遍历
提醒一下:用Iterator 迭代, 不是一样用了循环的嘛。
分享到:
相关推荐
如何遍历ArrayList的入门实例,可作为入门参考
本资源模拟java ArrayList Iterator的实现方式,其实也是为了介绍一下Iterator的设计模式。
在jni中操作arraylist对象,然后添加一个int型数据进去
ArrayList排序和遍历补充案例.java
遍历ArrayList存入HashMap中
import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ArrayListDemo { public static void main(String args[]){ List<String> list = new ArrayList(); list.add(...
用java编写的迭代器,实现10数字正反向遍历。
Java不同数据存储类型使用不同遍历方法效率研究 GitHub代码仓库 数据存储类型 ArrayList HashSet HashMap LinkedList 遍历方法 传统遍历方法 for(int i=0;i<list.size();i++) { String str = list.get(i); ... ...
图文并茂,能让大家很好的理解java中这个重要的知识点。 此文档需要wps或者office软件来查看,如果你没有此软件,到http://www.wps.com.cn 下载wps即可查看此文档。 注:本人所有资源都是共享的,的资源分都是0!
// 方法二:jdk1.5支持,用entrySet()和For-Each循环() Java代码 for (Map.Entry, String> m : emails.entrySet()) { logger.info("email-" + m.getKey() + ":" + m.getValue()); } for (Map....
主要介绍了java使用ArrayList遍历及效率比较,实例分析了ArrayList遍历的方法与使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
经典讲解List和ArrayList和Vector和HashTable和HashMap区别
主要介绍了Java ArrayList遍历修改代码实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
day07_18_ArrayList练习三_按指定格式遍历集合字符串
主要给大家介绍了ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论。相信对大家的理解和学习具有一定的参考价值,有需要的...
为什么ArrayList,Vector等都不支持循环中remove1 Vector 直接删除2 Vector 遍历元素2.1 for循环遍历2.2 迭代器循环2.3 任意方向遍历2.4 Vector的foreach3. Vector迭代器删除4. Vector不使用迭代器删除元素5. Vector...
从c/c++语言转向java开发,学习java语言list遍历的三种方法,顺便测试各种遍历方法的性能,测试方法为在ArrayList中插入1千万条记录,然后遍历ArrayList,发现了一个奇怪的现象,测试代码例如以下: package ...
主要介绍了ArrayList在for循环中使用remove方法移除元素的内容,介绍了具体代码实现,需要的朋友可以参考下。
主要介绍了java 中ArrayList迭代的两种实现方法的相关资料,Iterator与for语句的结合,需要的朋友可以参考下
对于列表而言,除了Iterator,还提供了一个功能更加强大的ListIterator。它可以实现逆序遍历列表中的元素。本示例将使用其逆序遍历ArrayList