使用标志或if子句更有效率吗?
在Java循环中,使用boolean
标志而不是if
语句会更高效吗?
看看这两位代码。
使用标志:
public boolean isSomethingForAnyone() {
boolean flag = false;
for (Item item : listOfItems) {
flag = flag || item.isSomething();
}
return flag;
}
使用if
语句:
public boolean isSomethingForAnyone() {
for (Item item : listOfItems) {
if (item.isSomething())
return true;
}
return false;
}
如果isSomething()
在第一次迭代中返回true
,那么使用if
语句的方法当然更快。 但是,平均速度是否更快?分支速度是否会变慢? 另外,如果循环速度更快,情况会有所不同吗? 在这里我使用了for-each循环来简化操作,我相信这比使用计数器的数组遍历要慢。
这两段代码并不完全相同。
尽管你只需要多次调用item.isSomething()
(与我的原始答案相反),但第一个版本仍然继续尝试迭代集合的其余部分。
想象一下Item.isSomething()
的实现,它修改了找到该项目的集合(如果它返回true
)。 此时,第一段代码会抛出一个ConcurrentModificationException
假设它是一个“常规”集合 - 而第二段代码只会返回true
。
从根本上讲,第二块代码更有效率:它只是遍历列表中的所有内容,而不是通过所有内容来确定答案。 很可能不同的表现是无关紧要的 - 特别是如果收藏量很小 - 但这取决于上下文。
你发现更可读的是一个不同的问题 - 效率可能不会很大,尽管这取决于上下文。 就我个人而言,我发现第二个版本更具可读性,更高效,所以我总是使用它。 (好吧,我会在if
语句的主体周围添加大括号,但仅此而已。)
你是否在循环中循环十亿次? 如果不是,那么差别可能无法衡量。
你可以看看生成的字节码,看看到底发生了什么,但编译器,jit和vm本身可能会优化掉任何差异。
如果你想知道你的机器上哪个“更快”,那么运行它。
如果我们想知道哪些需要更多的指令来执行,那么我们可以看看字节码。
对于第一种方法,我们得到了这个(调用javap -c
)
Code:
0: iconst_0
1: istore_1
2: getstatic #2 // Field listOfItems:Ljava/util/List;
5: invokeinterface #3, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
10: astore_2
11: aload_2
12: invokeinterface #4, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
17: ifeq 50
20: aload_2
21: invokeinterface #5, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
26: checkcast #6 // class Item
29: astore_3
30: iload_1
31: ifne 41
34: aload_3
35: invokevirtual #7 // Method Item.isSomething:()Z
38: ifeq 45
41: iconst_1
42: goto 46
45: iconst_0
46: istore_1
47: goto 11
50: iload_1
51: ireturn
我们感兴趣的是循环的内部,即第29-46行(第11-26行是迭代器的东西)。 所以关于10条指令。
对于第二种方法,我们得到这个:
Code:
0: getstatic #2 // Field listOfItems:Ljava/util/List;
3: invokeinterface #3, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
8: astore_1
9: aload_1
10: invokeinterface #4, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
15: ifeq 40
18: aload_1
19: invokeinterface #5, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
24: checkcast #6 // class Item
27: astore_2
28: aload_2
29: invokevirtual #7 // Method Item.isSomething:()Z
32: ifeq 37
35: iconst_1
36: ireturn
37: goto 9
40: iconst_0
41: ireturn
感兴趣的线是27-37。 所以7条指令。
从数字的角度来看,第二种方法出现在最前面(注意,我们假设所有堆栈操作都需要相同的时间来执行)。
链接地址: http://www.djcxy.com/p/74691.html上一篇: Is it more efficient to use a flag or an if clause?
下一篇: go build doesn't find my C standard library when compiling cgo package