java的for下标循环遍历和foreach循环遍历测试
来源:互联网 发布:知乎经历最多的人 编辑:程序博客网 时间:2024/06/05 04:32
java的for下标循环遍历和foreach循环遍历测试,到底哪个效率更高,下面写了代码测试:
测试针对 数组、ArrayList、LinkedList三种,分别做for下标循环遍历和foreach循环遍历:
import java.util.ArrayList;import java.util.LinkedList;import java.util.List;/** * 数组、ArrayList、LinkedList三种,分别做for下标循环遍历和foreach循环遍历 */public class TestFor {/** * 数组和ArrayList的大小 */private final int num = 1000000;/** * LinkedList的大小 */private final int numLinked = num / 10;private final int[] testArray = new int[num];private final List<Integer> testArrayList = new ArrayList<Integer>();private final List<Integer> testLinkList = new LinkedList<Integer>();private int test = 0;private void init() {for (int i = 0; i < num; i++) {testArray[i] = 0;testArrayList.add(0);}for (int i = 0; i < numLinked; i++) {testLinkList.add(0);}}private void testIndexArray() {final long startTime = System.currentTimeMillis();for (int i = 0; i < num; i++) {test = testArray[i];}final long stopTime = System.currentTimeMillis();System.out.println("下标数组 " + (stopTime - startTime));}private void testIterateArray() {final long startTime = System.currentTimeMillis();for (final int i : testArray) {test = testArray[i];}final long stopTime = System.currentTimeMillis();System.out.println("foreach数组 " + (stopTime - startTime));}private void testIndexArrayList() {final long startTime = System.currentTimeMillis();for (int i = 0; i < num; i++) {test = testArrayList.get(i);}final long stopTime = System.currentTimeMillis();System.out.println("下标ArrayList " + (stopTime - startTime));}private void testIterateArrayList() {final long startTime = System.currentTimeMillis();for (final int i : testArrayList) {test = testArrayList.get(i);}final long stopTime = System.currentTimeMillis();System.out.println("foreachArrayList " + (stopTime - startTime));}private void testIndexLinkList() {final long startTime = System.currentTimeMillis();for (int i = 0; i < numLinked; i++) {test = testLinkList.get(i);}final long stopTime = System.currentTimeMillis();System.out.println("下标LinkList " + (stopTime - startTime));}private void testIterateLinkList() {final long startTime = System.currentTimeMillis();for (final int i : testLinkList) {test = testLinkList.get(i);}final long stopTime = System.currentTimeMillis();System.out.println("foreachLinkList " + (stopTime - startTime));}public static void main(final String[] args) {final TestFor test = new TestFor();test.init();test.testIndexArray();test.testIterateArray();test.testIndexArrayList();test.testIterateArrayList();test.testIndexLinkList();test.testIterateLinkList();}}
结果:
下标数组 2
foreach数组 3
下标ArrayList 7
foreachArrayList 20
下标LinkList 5721
foreachLinkList 7
注意上述结果:数组和ArrayList容量为1000000,LinkedList是1000000 / 10(十分之一,因为遍历LinkedList实在太慢)
数组 :下标比foreach快,差别较小;
ArrayList :下标比foreach快,差别较大;
LinkedList:foreach比下标快,差别较大;
Java 中的 foreach 语法是 iterator(迭代器)的变形用法(可以看看反编译之后的代码),也就是说上面的 foreach 与下面的代码等价:
for (Iterator<Integer> i = list.iterator(); i.hasNext();) { sum += ((Integer)iterator.next()).intValue();}
lsit.iterator() 返回的迭代器对象是什么呢?查看JDK源码知道,ArrayList 类继承于 AbstractList 类,AbstracList 对 iterator 方法实现如下(ArrayList 类并没有重写该方法):
public Iterator<E> iterator() { return new Itr();}
方法直接创建一个 Itr 对象并将其返回,Itr 类其实是 AbstractList 类的一个内部类,Itr 类实现了 Iterator 接口,Itr 类部分源代码如下:
private class Itr implements Iterator<E> { /** * Index of element to be returned by subsequent call to next. */ int cursor = 0; /** * Index of element returned by most recent call to next or * previous. Reset to -1 if this element is deleted by a call * to remove. */ int lastRet = -1; public boolean hasNext() { return cursor != size(); } public E next() { checkForComodification(); try { E next = get(cursor); lastRet = cursor++; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } }}
从上面代码可以看出,迭代器同样也是通过对指向数组(ArrayList 是通过数组实现的)的下标进行递增来遍历整个数组的,这和通过下标方式访问列表计算平均值的方法是一样的,但是区别在于,迭代器需要调用 hasNext() 函数来判断指向数组的下标是否移到了数组末尾,而下标访问方式中并不需要对此进行检查;除此之外,在迭代器的 next() 方法中也出现了下标访问方式没有的 checkForComodification() 方法和 lastRet 变量赋值操作。这也就是通过 foreach 方式遍历耗时的原因。
那么ArrayList和LinkedList的区别是什么?
ArrayList数组实现了RandomAccess接口(随机存取接口),标识着ArrayList是一个可以随机存取的列表,即元素之间没有关联,即两个位置相邻的元素之间没有相互依赖关系,可以随机访问和存储。
说对于ArrayList,需要先创建一个迭代器容器,然后屏蔽内部遍历细节,对外提供hasNext、next等方法。
问题是ArrayList实现了RandomAccess接口,表明元素之间本没有关系,为了使用迭代器就需要强制建立一种互相“知晓”的关系,比如上一个元素可以判断是否有下一个元素,以及下一个元素是什么等关系,这也就是通过foreach遍历耗时的原因。
所以,以后如果是数组或ArrayList就用下标循环遍历,如果是LinkedList就用foreach循环遍历。当然 这只是在考虑性能时候的做法,如果不考虑性能还用foreach比较好,代码简洁。
over
- java的for下标循环遍历和foreach循环遍历测试
- Java数组和foreach遍历循环
- Java中foreach和for在循环遍历数组、集合方面的区别
- for循环的遍历
- iterator 遍历与for循环与foreach的优劣对比
- foreach循环遍历控件
- foreach循环遍历
- Mybatis 循环遍历 foreach
- JAVA for和foreach 遍历的效率
- Java中的foreach循环遍历详解
- Java中的foreach循环遍历详解
- foreach循环遍历数组和集合
- Java for循环遍历数组
- Java for循环和foreach循环的性能比较
- Java for循环和foreach循环的性能比较
- for循环和foreach循环的区别?
- foreach循环及Map遍历
- javascript数组循环遍历forEach
- 单例模式(Singleton)的6种实现
- <spark> 單機模式之環境創建
- Java虚拟机详解----JVM常见问题总结
- 线性可分支持向量机笔记
- 批量插入
- java的for下标循环遍历和foreach循环遍历测试
- 关于css的float
- Android之SD卡插拔广播
- KNN算法 总结
- 程序员久坐伤身,站起来,走出去,别回来
- 三点求圆心模板
- 打印基-3D打印社区之旅
- Android Framework中的Application Framework层介绍
- HALCON学习之算子大全