Java “与”的区别是什么;对于(int i=0,length=list.size;i<;length;i+;+;)而言;及;对于(int i=0;i<;list.size;i+;+;)而言;?

Java “与”的区别是什么;对于(int i=0,length=list.size;i<;length;i+;+;)而言;及;对于(int i=0;i<;list.size;i+;+;)而言;?,java,Java,我看到了两种编写循环的方法 for( int i = 0, length = list.size(); i < length; i++ ) for(int i=0,length=list.size();i

我看到了两种编写循环的方法

for( int i = 0, length = list.size(); i < length; i++ )
for(int i=0,length=list.size();i

for(int i=0;i

他们的表现一样吗?jvm会优化差异吗?

请尝试使代码更易于阅读,以帮助回答您的问题

以下测试基于javase 8:

我将列出两种不同代码的java字节码:

public void gg1(List<String> list){
    for(int i = 0, length = list.size(); i < length; i++){

    }
}
public void gg1(列表){
for(int i=0,length=list.size();i
字节码为:

public gg1(Ljava/util/List;)V
   L0
   LINENUMBER 10 L0
   ICONST_0
   ISTORE 2
  L1
   ALOAD 1
   INVOKEINTERFACE java/util/List.size ()I
   ISTORE 3
  L2
   GOTO L3
  L4
  FRAME APPEND [I I]
   IINC 2 1
  L3
  FRAME SAME
   ILOAD 2
   ILOAD 3
   IF_ICMPLT L4
  L5
   LINENUMBER 13 L5
   RETURN
  L6
   LOCALVARIABLE this Lcom/trans/test/Test14; L0 L6 0
   LOCALVARIABLE list Ljava/util/List; L0 L6 1
   // signature Ljava/util/List<Ljava/lang/String;>;
   // declaration: java.util.List<java.lang.String>
   LOCALVARIABLE i I L1 L5 2
   LOCALVARIABLE length I L2 L5 3
   MAXSTACK = 2
   MAXLOCALS = 4
public gg2(Ljava/util/List;)V
  L0
   LINENUMBER 16 L0
   ICONST_0
   ISTORE 2
  L1
   GOTO L2
  L3
  FRAME APPEND [I]
   IINC 2 1
  L2
  FRAME SAME
   ILOAD 2
   ALOAD 1
   INVOKEINTERFACE java/util/List.size ()I
   IF_ICMPLT L3
  L4
   LINENUMBER 19 L4
   RETURN
  L5
   LOCALVARIABLE this Lcom/trans/test/Test14; L0 L5 0
   LOCALVARIABLE list Ljava/util/List; L0 L5 1
   // signature Ljava/util/List<Ljava/lang/String;>;
   // declaration: java.util.List<java.lang.String>
   LOCALVARIABLE i I L1 L4 2
   MAXSTACK = 2
   MAXLOCALS = 3
公共gg1(Ljava/util/List;)V L0 10号线L0 ICONST_0 史前2 L1 阿洛德1号 INVOKEINTERFACE java/util/List.size()I 史前3 L2 转到L3 L4 帧附加[I] IINC 2 1 L3 框架相同 伊洛德2号 伊洛德3号 IF_ICMPLT L4 L5 线路号13 L5 返回 L6 本地变量此Lcom/trans/test/Test14;L0 L6 0 LOCALVARIABLE list Ljava/util/list;L0 L6 1 //签名Ljava/util/List; //声明:java.util.List 本地变量i L1 L5 2 本地可变长度I L2 L5 3 MAXSTACK=2 最大局部数=4
现在在另一个代码中:

 public void gg2(List<String> list){
    for(int i = 0; i < list.size(); i++){

    }
}
public void gg2(列表){
对于(int i=0;i
字节码为:

public gg1(Ljava/util/List;)V
   L0
   LINENUMBER 10 L0
   ICONST_0
   ISTORE 2
  L1
   ALOAD 1
   INVOKEINTERFACE java/util/List.size ()I
   ISTORE 3
  L2
   GOTO L3
  L4
  FRAME APPEND [I I]
   IINC 2 1
  L3
  FRAME SAME
   ILOAD 2
   ILOAD 3
   IF_ICMPLT L4
  L5
   LINENUMBER 13 L5
   RETURN
  L6
   LOCALVARIABLE this Lcom/trans/test/Test14; L0 L6 0
   LOCALVARIABLE list Ljava/util/List; L0 L6 1
   // signature Ljava/util/List<Ljava/lang/String;>;
   // declaration: java.util.List<java.lang.String>
   LOCALVARIABLE i I L1 L5 2
   LOCALVARIABLE length I L2 L5 3
   MAXSTACK = 2
   MAXLOCALS = 4
public gg2(Ljava/util/List;)V
  L0
   LINENUMBER 16 L0
   ICONST_0
   ISTORE 2
  L1
   GOTO L2
  L3
  FRAME APPEND [I]
   IINC 2 1
  L2
  FRAME SAME
   ILOAD 2
   ALOAD 1
   INVOKEINTERFACE java/util/List.size ()I
   IF_ICMPLT L3
  L4
   LINENUMBER 19 L4
   RETURN
  L5
   LOCALVARIABLE this Lcom/trans/test/Test14; L0 L5 0
   LOCALVARIABLE list Ljava/util/List; L0 L5 1
   // signature Ljava/util/List<Ljava/lang/String;>;
   // declaration: java.util.List<java.lang.String>
   LOCALVARIABLE i I L1 L4 2
   MAXSTACK = 2
   MAXLOCALS = 3
公共gg2(Ljava/util/List;)V L0 线路号16 L0 ICONST_0 史前2 L1 转到L2 L3 帧附加[I] IINC 2 1 L2 框架相同 伊洛德2号 阿洛德1号 INVOKEINTERFACE java/util/List.size()I IF_ICMPLT L3 L4 线路号19 L4 返回 L5 本地变量此Lcom/trans/test/Test14;L0 L5 0 LOCALVARIABLE list Ljava/util/list;L0 L5 1 //签名Ljava/util/List; //声明:java.util.List 局部变量i L1 L4 2 MAXSTACK=2 最大局部变量=3
可以看出,list.size()方法将在gg2的每次迭代中调用,并在方法gg1中调用一次。因此,gg1更高效


我希望这有助于回答你的问题

当在循环块中更改大小时,这两个for循环不相等。第一个可能会因索引超出范围而失败,或者可能会丢失添加的元素


性能:编译器优化了最常见的情况。因此,我不会做任何特别的事情来尝试优化像循环集合这样常见的东西。

关键区别在于第一种方法只调用一次
list.size()
,而不是每次迭代。对于一个简单的列表来说,它不太可能有用,但是当计算
长度的成本很高时,它会很有用;例如,当

停止担心微观优化,编写更容易理解的代码时。很好的“?”问题,但正如@MitchWheat所说,“编写更容易理解的代码”。不要担心优化这样的东西,因为它的速度只会快几毫秒,一毫秒只是千分之一秒,毫秒?更像microsecond@TyQ. 实际上,Java编译器甚至可以将两个版本优化为同一个版本。但是,是的,米奇·麦特说的……如果你对一个编译器进行微优化,即使是下一次补丁更新也可能会让你的代码悲观……我还尝试了两种不同写入类型之间的性能。