在带有许多 if 语句的 for 循环中使用 continue 时性能是不是有所提高?
Posted
技术标签:
【中文标题】在带有许多 if 语句的 for 循环中使用 continue 时性能是不是有所提高?【英文标题】:Is performance gained when using continue in a for-loop with many if-statements?在带有许多 if 语句的 for 循环中使用 continue 时性能是否有所提高? 【发布时间】:2016-01-15 12:55:35 【问题描述】:我在一个 java 程序中有一个 for 循环,它遍历一组映射。
在循环中,我有大约 10 个不同的 if 语句,它们检查每个映射中每个键的名称。
例子:
for (<String, Object> map : object.entrySet())
if (map.getKey().equals.("something")
do_something;
continue;
if (map.getKey().equals.("something_else")
do_something_else;
continue;
if ...
在添加这样的 continue 语句时,我会获得任何性能吗?
当我在 IDE 中单步执行我的代码并且没有这些 continue 语句时,即使第一个匹配,也会测试每个 if 语句。
如果我有这样的它们并且第一个 if 匹配,for 循环将跳过接下来的 9 个 if 语句并继续下一个对象。 也许编译后的代码会以不同的方式处理它,而添加的 continue 语句实际上会使循环变慢?
【问题讨论】:
Inside the loop I have around 10 different if-statements which checks the name of each key inside the each map.
我会停在那里并确保不会发生这种情况。没关系性能,那是糟糕的代码。先写干净的代码,再考虑性能。 (更不用说更简洁的代码更有可能表现得更好。)
@komen 我知道你已经接受了一个答案,但我已经添加了我的答案,我相信它可以认真改进你的代码。请看一下。 tks.
【参考方案1】:
不要一直使用continue
,只需执行一次getKey()
并使用else if
:
for (Map.Entry<String, Object> entry : map.entrySet())
String key = entry.getKey();
if (key.equals("something"))
// ...
else if (key.equals("something else"))
// ...
或使用switch
声明:
for (Map.Entry<String, Object> entry : map.entrySet())
switch (entry.getKey())
case "something":
// ...
break;
case "something else":
// ...
break;
【讨论】:
更不用说键应该是枚举而不是字符串。 for switch 语句:如果情况是“其他”,那么 entry.getKey() 也会被调用两次,对吧? @HRgiger 不,entry.getKey()
只会为 switch
语句调用一次,无论有多少情况。【参考方案2】:
如果您希望当前迭代在第一个条件评估为真后结束,您应该使用if-else-if-...-else
。在我看来,这比使用continue
更清楚,因为这就是该语法存在的目的。
for (<String, Object> map : object.entrySet())
if (map.getKey().equals.("something")
do_something;
else if (map.getKey().equals.("something_else")
do_something_else;
else if (...)
...
... else
...
【讨论】:
谢谢!更改为 else if 并且执行的行为与 continue 完全相同,但使代码看起来更清晰。【参考方案3】:使用您当前的实现,是的,您可以通过使用 continue
关键字跳过剩余的 if 语句来获得性能提升,尽管只有十个“if”语句的常量,它并没有那么糟糕(10n = O(n ) 时间)。话虽如此,正如 Eran 所说,解决这个问题的更实际的方法是使用 else if
语句,这将达到您当前使用的相同结果。
【讨论】:
【参考方案4】:因为您只有几个值,IMO,如果您将字符串映射到整数,您将在此处获得真正的性能改进,因为 int 比较是远比字符串比较快。
看看这个
public class Lab1
public static void main(String[] args)
usingStrings();
usingInts();
private static void usingInts()
int[] samples = new int[100000000];
int[] values = 1,2,3,4;
for(int i=0;i<samples.length-1;i++)
samples[i] = values[(int)(Math.random()*values.length)];
int total = 0;
long ini = System.currentTimeMillis();
for(int i=0;i<samples.length-1;i++)
if (1 == (samples[i]))
total+=doSomeJob();
else if (2 == (samples[i]))
total+=doSomeJob();
else if (3 == (samples[i]))
total+=doSomeJob();
else
total+=doSomeJob();
long end = System.currentTimeMillis();
System.out.println("Ints="+(end-ini));
private static void usingStrings()
String[] samples = new String[100000000];
String[] values = "one mule","two mules","three mules","four mules";
for(int i=0;i<samples.length-1;i++)
samples[i] = values[(int)(Math.random()*values.length)];
int total = 0;
long ini = System.currentTimeMillis();
for(int i=0;i<samples.length-1;i++)
if ("one mule".equals(samples[i]))
total+=doSomeJob();
else if ("two mules".equals(samples[i]))
total+=doSomeJob();
else if ("three mules".equals(samples[i]))
total+=doSomeJob();
else
total+=doSomeJob();
long end = System.currentTimeMillis();
System.out.println("Strings="+(end-ini));
/**
*
*/
private static int doSomeJob()
int c = 0;
for(int i=0;i<1000;i++)
c++;
return c;
输出
Strings=962
Ints=6
这实际上是 DBMS 索引在幕后的工作方式
【讨论】:
不,这不是“DBMS 索引如何在幕后工作”。大多数表键都太长而无法首先映射到整数,并且 DBMS 实现不使用if-elses
链,无论如何都应该用switch
替换。以上是关于在带有许多 if 语句的 for 循环中使用 continue 时性能是不是有所提高?的主要内容,如果未能解决你的问题,请参考以下文章