在带有许多 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 时性能是不是有所提高?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery if 语句在 for 循环中不起作用

C# - 带有 if 语句的 Foreach 循环

在 vuejs 中使用 if 语句循环

作业3---for语句及分支结构else-if

Linux Shell:Shell循环语句

如何在 html 标记(如段落)中使用 if 语句显示 for 循环的结果