好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

对于Java中的For循环和Foreach,哪个更快

Java遍历集合有两种方法。一个是最基本的for循环,另一个是jdk5引入的for each。通过这种方法,我们可以更方便地遍历数组和集合。但是你有没有想过这两种方法?哪一个遍历集合更有效?

for-each实现方法

For-each不是一种新语法,而是Java的语法糖。在编译时,编译器将此代码转换为迭代器实现,并将其编译为字节码。

语法糖:

语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

我们可以通过执行命令javap-verbose-Testforeach反编译以下编译代码:

 public   class   TestForeach  {  List  <  Integer  >   integers ;  public   void   testForeach (){  for ( Integer   i  :  integers ){

        }
    }
}

获得的详细字节码如下:

 public   void   testForeach ();  descriptor : () V   flags :  ACC_PUBLIC   Code :  stack  =  1 ,  locals  =  3 ,  args_size  =  1   0 :  aload_0   1 :  getfield   #2   // Field integers:Ljava/util/List;   4 :  invokeinterface   #3 ,  1   // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;   9 :  astore_1   10 :  aload_1   11 :  invokeinterface   #4 ,  1   // InterfaceMethod java/util/Iterator.hasNext:()Z   16 :  ifeq   32   19 :  aload_1   20 :  invokeinterface   #5 ,  1   // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;   25 :  checkcast   #6   // class java/lang/Integer   28 :  astore_2   29 :  goto   10   32 :  return   LineNumberTable :  line   11 :  0   line   13 :  29   line   14 :  32   LocalVariableTable :  Start   Length   Slot   Name   Signature   29   0   2   i   Ljava  /  lang  /  Integer ;  0   33   0   this   Ltest  /  TestForeach ;
}

此字节码的一般含义是使用getfileld命令来获取integers变量并且调用List.iterator来获取迭代器实例和调用iterator.hasNext。如果返回true,调用iterator.next方法。

请看,这是迭代器遍历集合的实现逻辑。

基准测试

现在让我们使用for循环方法和for-each方法进行测试。

 public   class   ForLoopTest  {  public   static   void   main ( String []  args ) {  List  <  Integer  >   arrayList   =   new   ArrayList  <  > ();  for  ( int   i   =   0 ;  i   <   10000000 ;  i  ++ ) {  arrayList . add ( i );
        }  long   arrayListStartTime   =   System . currentTimeMillis ();  for  ( int   i   =   0 ;  i   <   arrayList . size ();  i  ++ ) {  arrayList . get ( i );
        }  long   arrayListCost   =  System . currentTimeMillis () -  arrayListStartTime ;  System . out . println ( "ArrayList for loop traversal cost: "  +   arrayListCost );  long   arrayListForeachStartTime   =   System . currentTimeMillis ();  for  ( Integer   integer  :  arrayList ) {

        }  long   arrayListForeachCost   =  System . currentTimeMillis () -  arrayListForeachStartTime ;  System . out . println ( "ArrayList foreach traversal cost: "  +   arrayListForeachCost );

这是测试结果:

如你所见,结果是显而易见的。对于ArrayList,使用For循环方法的性能优于For each方法。

我们可以说for循环比for-each好吗?

答案是否定的。在下一个基准测试中,我们将ArrayList更改为LinkedList。 同样,这里是测试结果。

原因分析

一些初学者可能想知道为什么ArrayList使用for循环方法遍历得更快,而LinkedList则更慢,速度也非常慢?

这由ArrayList和LinkedList数据结构决定。 ArrayList底层使用数组存储元素。数组是连续的内存空间。数据可以通过索引获得。时间复杂度为O(1),因此速度很快。

LinkedList的底层是一个双向链表。使用for循环实现遍历,每次都需要从链表的头节点开始。时间复杂度为O(n*n)。

结论 使用ArrayList时,for循环方法更快,因为for-each由迭代器实现,并且需要执行并发修改验证。 使用LinkedList时,for-each比for循环快得多,因为LinkedList是通过使用双向链表实现的。每个寻址都需要从头节点开始。如果我们需要遍历LinkedList,我们需要避免使用for循环。 使用迭代器模式,for-each不需要关心集合的具体实现。如果需要替换集合,无需修改代码即可轻松替换。

原文地址:https://HdhCmsTesttoutiao测试数据/article/7133964465154425374/

查看更多关于对于Java中的For循环和Foreach,哪个更快的详细内容...

  阅读:13次