RT,java中使用这两种方法哪个的效率高。还有,和普通的for循环比起来,哪个效率更高。

解决方案 »

  1.   

    拿 foreach 迭代集合实际也是拿 Iterator 迭代的,语法上更简洁了。
      

  2.   

    List list = new ArrayList();
    for (Object item : list) {
    System.out.println(item.toString());
    }相当于: List list = new ArrayList();
    Object obj;
    for (Iterator iterator = list.iterator(); iterator.hasNext();) {
    obj = iterator.next();
    System.out.println(obj.toString())
    }
      

  3.   

    反编译一下可以看到里面还是通过迭代器来实现的。
    文档里也有说明:
    public interface Iterable<T>实现这个接口允许对象成为 "foreach" 语句的目标。 
    编译之后通过Iterator<T> iterator()方法获得的迭代器来实现循环访问。
      

  4.   

    对于ArrayList,Vector 其核心是一个数组, 如果明确知道List的实例是ArrayList,Vector,当然用 for(int i=0; i<lst.size();i++){} 这种方式是最快的.  当然用Iterator 的话,其实是相关无几,Iterator 基本上都是指针操作, Iterator本身的处理会增加一点点的开销,跟踪一下源码就可以知道.Iterator 好处:通用,对于所有集合,使用Iterator性能都一样, 客户端自身不维护遍历集合的"指针",所有的内部状态(如当前元素位置,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂方法生成,因此,它知道如何遍历整个集合。
    客户端从不直接和集合类打交道,它总是控制Iterator,向它发送"向前","向后","取当前元素"的命令,就可以间接遍历整个集合。for(i=0;...) 方法有一个缺点: 如果List的实例是LinkedList等非"数组"存储方式的时候,遍历集合的开销会差别很大! 就以LinkedList来说,以下是get(i)方法来取元素的主要代码, 我们可以看到,LinkedList 内的get(i)方法,用了循环方式来返回元素,性能肯定会差.        if (index < 0 || index >= size)
                throw new IndexOutOfBoundsException("Index: "+index+
                                                    ", Size: "+size);
            Entry<E> e = header;
            if (index < (size >> 1)) {
                for (int i = 0; i <= index; i++)
                    e = e.next;
            } else {
                for (int i = size; i > index; i--)
                    e = e.previous;
            }
            return e;
           
      

  5.   


    再看一下,ArrayList 的 get(index) 方法:
      return (E) elementData[index];因为内部是数组存储的,所以直接返回数组元素,所以肯定是最快的方法 .
      

  6.   

    说的很详细,不过楼主的问题是foreach循环和Iterator的效率问题。
      

  7.   


    oh,no, 搞错了, 只看到for 没看到到foreach. 而且是针对集合,而不是List.foreach 不知内部是不会根据不同实例类型作优化,如果没有,则可能内部就是用Iterator方法(具体可以试试跟踪一下源代码),如果这样效率应该是一样的. 
      

  8.   

    写一个foreach的,然后用jad反编译就能比较出来了。
      

  9.   


    谢谢,提醒,我试了,可以告诉楼主,for(xx:col) 这种形式编译后就是等于 for(Iterator iterator = list.iterator(); iterator.hasNext();)
    所以效率是一样的。另贴一下,测试代码说明一下for + get(i) 的方法 与 Iterator 的性能差别.
       public static void main(String[] args)
        { List<Integer> list = new ArrayList<Integer>();
            for(int i=0;i<5000000 ;i++){
                list.add(11);
            }
            
            long start = System.currentTimeMillis();
            int size= list.size();
            int c1=1;
            for(int i=0;i<size;i++){
                c1 = list.get(i);
            }
            System.out.println("for + get(i)方法: " 
             + (System.currentTimeMillis()-start));
            
        
            long start2 = System.currentTimeMillis();
            for(int c2:list){
            }
            System.out.println("Iterator(foreach)方法:" 
             + (System.currentTimeMillis()-start2));     }
      

  10.   

    将ArrayList 改成LinkedList,并把集合的元素改少(如果不改少,时间会很长...),可以测试LinkedList的效果.
      

  11.   

    楼主,我用100000最小数据测试了一下:import java.util.*;
    public class CMPfor
    {
    final long N = 1000000;
    private ArrayList<Integer> aT = new ArrayList<Integer>(); private LinkedList<Integer> LT = new LinkedList<Integer>(); public CMPfor(){
    for(int i = 0; i < N; i++){
    aT.add(i);
    }
    for(int i = 0; i < N; i++){
    LT.add(i);
    }
    } public void forTest(List<Integer> t){
    for(int i = 0; i < t.size();i++){
    t.get(i);
    }
    }
    public void foreachTest(List<Integer> t){
    for(int j : t){

    }
    } public void iteratorTest(List<Integer> t){
    Iterator it = t.iterator();
    while(it.hasNext()){
    it.next();
    }
    }
    public void whileTest(List<Integer> t){
    int i = 0;
    while(i < N){
    t.get(i);
    i++;
    }
    } public static void main(String[] args){

    CMPfor cf = new CMPfor(); long a,b; System.out.println("ArrayList Test:");
    a=System.currentTimeMillis(); cf.forTest(cf.aT); b=System.currentTimeMillis(); System.out.println("forTest: "+(b-a)+"ms"); a=System.currentTimeMillis(); cf.foreachTest(cf.aT); b=System.currentTimeMillis(); System.out.println("foreachTest: "+(b-a)+"ms"); a=System.currentTimeMillis(); cf.iteratorTest(cf.aT); b=System.currentTimeMillis(); System.out.println("iteratorTest: "+(b-a)+"ms");
    a=System.currentTimeMillis(); cf.whileTest(cf.aT); b=System.currentTimeMillis(); System.out.println("whileTest: "+(b-a)+"ms");
    System.out.println("LinkedList Test:");
    a=System.currentTimeMillis(); cf.forTest(cf.LT); b=System.currentTimeMillis(); System.out.println("forTest: "+(b-a)+"ms"); a=System.currentTimeMillis(); cf.foreachTest(cf.LT); b=System.currentTimeMillis(); System.out.println("foreachTest: "+(b-a)+"ms"); a=System.currentTimeMillis(); cf.iteratorTest(cf.LT); b=System.currentTimeMillis(); System.out.println("iteratorTest: "+(b-a)+"ms");
    a=System.currentTimeMillis(); cf.whileTest(cf.LT); b=System.currentTimeMillis(); System.out.println("whileTest: "+(b-a)+"ms");
    }
    }
    结果如下:
    ArrayList Test:
    forTest:        10ms
    foreachTest:    20ms
    iteratorTest:   10ms
    whileTest:      10ms
    LinkedList Test:
    forTest:        108135ms
    foreachTest:    10ms
    iteratorTest:   10ms
    whileTest:      120644ms
    另一组运行结果:
    ArrayList Test:
    forTest:        10
    foreachTest:    10
    iteratorTest:   20
    whileTest:      0
    LinkedList Test:
    forTest:        105852
    foreachTest:    10
    iteratorTest:   20
    whileTest:      104851事实证明:
    不同的集合类型处理的时间不同
    LinkedList 不要用for和while
    foreach比Iterator快
    ArayList中,遍历速度:while>for>foreach
      

  12.   

    17楼的测试本身是有问题的:
     public void forTest(List<Integer> t){
            for(int i = 0; i < t.size();i++){
                t.get(i);
            }
        }
        public void foreachTest(List<Integer> t){
            for(int j : t){
                
            }
        }
    for测试直接用t.get(i);
    foreach测试却
    for(int j : t){
                
            }
    中间增加了Integer到int的转换过程。
      

  13.   

    每次增加的是Integer.intValue操作,使比较失去了意义。
      

  14.   

    2楼也说过了,使用foreach和直接使用Iterator的代码其实是一样的,不过是编译器自动处理的而已。
    代码都是一样的,性能差距是怎么来的呢?
      

  15.   

    12楼不知道想表达什么, 你想说while比for 效率高吗?结论是这样的,
    1.for 与 while 性能是一样的,这个很多人都测试过了.2. 另外 foreach 与 for + iterator 也是一样的,为什么一样上面已经说了,编译器最终把foreach编译成for + iterator,而且已经测试过了,事实跟理论一致.3.至于LinkedList为什么这么长时间, 我在6楼已经说得很清楚了. 所以说for + get(i) 方法不够"通用"4. foreach(for + iterator) 与 for + get(i) 性能差别很少(6楼已经说过了),iterator因为对所有集合效率几乎一样,所以很通用, 如果你的程序是面向接口的,一般就得用比较通用的iterator, 绝大多数情况下,我们都不必介意效率有那么一点儿差别, 我们需要知道有这么一点儿差别就是了. 以下对5000000条记录的ArrayList的测试结果,已经运行了十几次,每次结果差不多: 
    1.for + get(i)方法: 94
    2.Iterator(foreach)方法:265
    3.While + get(i)方法:94
    4.for iterator方法:281
    package myTest;import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.SortedMap;
    import java.util.Vector;public class Test {
       public static void main(String[] args)
        {    List<Integer> list = new ArrayList<Integer>();
            for(int i=0;i<5000000 ;i++){
                list.add(11);
            }
            
            
            int size= list.size();
            int c1=1;
            long start = System.currentTimeMillis();
            for(int i=0;i<size;i++){
                c1 = list.get(i);
            }
            long end = System.currentTimeMillis()-start;
            System.out.println("for + get(i)方法: " + end);
            
            
            start = System.currentTimeMillis();
            for(int c2:list){
            }
            end = System.currentTimeMillis()-start;
            System.out.println("Iterator(foreach)方法:" + end);
            
            
            int i = 0;
            size = list.size();
            start = System.currentTimeMillis();
            while(i<size){
             c1 = list.get(i); 
             i++;
            }
            end = System.currentTimeMillis()-start;
            System.out.println("While + get(i)方法:" + end);
            
            start = System.currentTimeMillis();
            for(Iterator iterator = list.iterator(); iterator.hasNext();) {
             c1 = (Integer) iterator.next();
            }
            end = System.currentTimeMillis()-start;
            System.out.println("for iterator方法:" + end);
         }
      
    }
      

  16.   

    12楼有什么问题吗?只是后面怀疑了17楼的测试结果:foreach比Iterator快 楼上想说什么?
      

  17.   

    我运行的结果大多数情况下Iterator比foreach 快10ms左右, 有时候foreach会快一点, 我认为这点偏差对于我们的实际应用可以忽略不计. 根本不用理会. 
      

  18.   

    写段程序测试下:
    public void testForEach() {
    List<String> list = new ArrayList<String>();
    int startNumber = 2;
    for (int i = 10; i < 25; i++) {
    double maxSize = Math.pow(startNumber, i);
    for (int index = 0; index < maxSize; index++) {
    list.add("");
    }
    Long start = System.currentTimeMillis();
    for (int jj = 0; jj < maxSize; jj++) {
    String result = list.get(jj);
    }
    Long end = System.currentTimeMillis();
    long total1 = (end - start); start = System.currentTimeMillis();
    for (String result : list) { }
    end = System.currentTimeMillis();
    long total2 = (end - start);
    System.out.println(i + ":  totalSzie: " + maxSize + ", and get  took: "
    + total1 + ", while forEach took: " + total2);
    list.clear();
    }
    }结果如下:
    10:  totalSzie: 1024.0, and get  took: 0, while forEach took: 0
    11:  totalSzie: 2048.0, and get  took: 0, while forEach took: 0
    12:  totalSzie: 4096.0, and get  took: 0, while forEach took: 0
    13:  totalSzie: 8192.0, and get  took: 0, while forEach took: 0
    14:  totalSzie: 16384.0, and get  took: 0, while forEach took: 0
    15:  totalSzie: 32768.0, and get  took: 15, while forEach took: 0
    16:  totalSzie: 65536.0, and get  took: 0, while forEach took: 0
    17:  totalSzie: 131072.0, and get  took: 0, while forEach took: 0
    18:  totalSzie: 262144.0, and get  took: 0, while forEach took: 15
    19:  totalSzie: 524288.0, and get  took: 0, while forEach took: 31
    20:  totalSzie: 1048576.0, and get  took: 15, while forEach took: 32
    21:  totalSzie: 2097152.0, and get  took: 31, while forEach took: 79
    22:  totalSzie: 4194304.0, and get  took: 62, while forEach took: 141