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编译器甚至可以将两个版本优化为同一个版本。但是,是的,米奇·麦特说的……如果你对一个编译器进行微优化,即使是下一次补丁更新也可能会让你的代码悲观……我还尝试了两种不同写入类型之间的性能。