Joe*_*Joe 45 java optimization coding-style
List<String> flowers = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)
我的for循环目前看起来像这样......
for (int i = 0; i < flowers.size(); i++) {
...
}
Run Code Online (Sandbox Code Playgroud)
或者我应该改变它看起来像下面给出的代码
int size = flowers.size();
for (int i = 0; i < size; i++) {
...
}
Run Code Online (Sandbox Code Playgroud)
哪个性能更高(假设我有大量的花),我猜它应该是后者.
Jig*_*shi 57
最好使用for-each循环 [更易读]
for (Flower flower :flowers){
//...
}
Run Code Online (Sandbox Code Playgroud)
我已经转储使用javap以下代码的说明:
public void forLoop1() {
List<String> lst = new ArrayList<String>();
for (int i = 0; i < lst.size(); i++) {
System.out.println("hi");
}
}
public void forLoop2() {
List<String> lst = new ArrayList<String>();
int size = lst.size();
for (int i = 0; i < size; i++) {
System.out.println("hi");
}
}
Run Code Online (Sandbox Code Playgroud)
public void forLoop1();
Code:
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: astore_1
8: iconst_0
9: istore_2
10: iload_2
11: aload_1
12: invokeinterface #4, 1; //InterfaceMethod java/util/List.size:()I
17: if_icmpge 34
20: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
23: ldc #6; //String hi
25: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
28: iinc 2, 1
31: goto 10
34: return
public void forLoop2();
Code:
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: invokeinterface #4, 1; //InterfaceMethod java/util/List.size:()I
14: istore_2
15: iconst_0
16: istore_3
17: iload_3
18: iload_2
19: if_icmpge 36
22: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
25: ldc #6; //String hi
27: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
30: iinc 3, 1
33: goto 17
36: return
Run Code Online (Sandbox Code Playgroud)
它不适合我.
java版"1.6.0_22"Java(TM)SE运行时环境(版本1.6.0_22-b04)Java HotSpot(TM)客户端VM(版本17.1-b03,混合模式,共享)
因此,如果您需要从提到的两个中进行选择,请选择第二个,但我个人会选择for-each.
来自Joshua Bloch的Effective Java中的第46项:
在1.5版中引入的for-each循环通过完全隐藏迭代器或索引变量来消除混乱和错误的机会.由此产生的习语同样适用于集合和数组:
Run Code Online (Sandbox Code Playgroud)// The preferred idiom for iterating over collections and arrays for (Element e : elements) { doSomething(e); }当您看到冒号(:)时,将其读作"in".因此,上面的循环读作"对于元素中的每个元素e".请注意,使用for-each循环没有性能损失,即使对于数组也是如此.实际上,在某些情况下,它可能比普通的for循环提供轻微的性能优势,因为它只计算一次数组索引的限制.虽然您可以手动执行此操作(第45项),但程序员并不总是这样做.
Dav*_*nco 20
很抱歉,但@ Jigar的回答不正确.这是正确的答案.(tldr;不要使用for : each).
import java.util.ArrayList;
import java.util.List;
public class LoopTest {
public static void main(String s[]) {
long start, end;
List<Integer> a = new ArrayList<Integer>();
for (int i = 0; i < 2500000; i++) {
a.add(i);
}
///// TESTING FOR : EACH LOOP
start = System.currentTimeMillis();
for (Integer j : a) {
int x = j + 3;
}
end = System.currentTimeMillis();
System.out.println(end - start
+ " milli seconds for [ Integer j : a ] ");
////// TESTING DEFAULT LOOP
start = System.currentTimeMillis();
for (int i = 0; i < a.size(); i++) {
int x = a.get(i) + 3;
}
end = System.currentTimeMillis();
System.out.println(end - start
+ " milli seconds for [ int i = 0; i < a.length; i++ ] ");
////// TESTING SLIGHTLY OPTIMIZED LOOP
start = System.currentTimeMillis();
int size = a.size();
for (int i = 0; i < size; i++) {
int x = a.get(i) + 3;
}
end = System.currentTimeMillis();
System.out.println(end - start
+ " milli seconds for [ int i = 0; i < size; i++ ] ");
//// TESTING MORE OPTIMIZED LOOP
start = System.currentTimeMillis();
for (int i = size; --i >= 0;) {
int x = a.get(i) + 3;
}
end = System.currentTimeMillis();
System.out.println(end - start
+ " milli seconds for [ int i = size; --i >= 0; ] ");
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
96 milli seconds for [ Integer j : a ]
57 milli seconds for [ int i = 0; i < a.length; i++ ]
31 milli seconds for [ int i = 0; i < size; i++ ]
31 milli seconds for [ int i = size; --i >= 0; ]
Run Code Online (Sandbox Code Playgroud)
您可以自己决定,但JVM优化器的归因太多了.你仍然必须聪明地使用自己的代码,使用for : each符号并不是一个好主意(几乎所有).如您所见,通过将大小放在自己的变量中,您有一个好主意.
尽管其中一些优化可能依赖于JVM(有些可能会与JIT相关),但了解Java的作用以及Java不执行的操作非常重要.
Raz*_*aze 11
JVM无法对其进行优化,因为它size()是一种方法,JVM无法(也不会尝试)确定size()在此上下文中始终返回相同的值.提供的size()值不会改变,第二个值会稍微提高性能,但增益是如此,如此轻微以至于你甚至不必考虑使用它.
如果性能至关重要,请使用普通计数器循环,但是对于98%的情况,代码的清晰度和简单性更为重要(如1000x或更多),您应该使用for-each循环.
@David指出使用计数器更快,但我要指出,即使是10,000个条目,差异也是亚微秒.
如果你有超过10,000个条目的集合,很可能你不应该蛮力迭代所有可能性.更像是一个像Map一样的查找集合是一个更好的解决方案,无论你想到什么.如果您的参赛作品远远少于10,000,则表现不太可能变得重要.
如果在迭代时数组列表发生更改,则行为会有所不同.但我想你不这样做.根据我的测试,后者通常更快(特别是在像Android这样的系统上).我会写如下:
for (int i = 0, size = flowers.size(); i < size; i++) {
...
}
Run Code Online (Sandbox Code Playgroud)