Is ++i really faster than i++ in for-loops in java

2019-01-17 14:53发布

In java I usually make a for-loop like following:

for (int i = 0; i < max; i++) {
   something
}

But recently a colleague typed it so:

for (int i = 0; i < max; ++i) {
   something
}

He said the latter would be faster. Is that true?

11条回答
相关推荐>>
2楼-- · 2019-01-17 15:03

In Java there should be no difference - any modern compiler* should generate the same byte code (just an iinc) in both cases since the result of the increment expression is not being used directly.
There is a third option, still the same byte code*:

for (int i = 0; i < max; i += 1) {
   something
}

* tested with Eclipse's compiler

查看更多
唯我独甜
3楼-- · 2019-01-17 15:05

No, it's not true. You could measure the performance by timing each loop for a large number of iterations, but I'm fairly certain they will be the same.

The myth came from C where ++i was regarded as faster than i++ because the former can be implemented by incremeting i then returning it. The latter might be implemented by copying the value of i to a temporary variable, incrementing i, then returning the temporary. The first version doesn't need to make the temporary copy and so many people assume that it is faster. However if the expression is used as a statement modern C compilers can optimize the temporary copy away so that there will be no difference in practice.

查看更多
Luminary・发光体
4楼-- · 2019-01-17 15:09

Even if it is, which I very much doubt, your colleague should really have better things to spend his time learning than how to optimise a loop expression.

查看更多
戒情不戒烟
5楼-- · 2019-01-17 15:10

This question needed some Java byte code. Consider the following code:

public class PostPre {
    public static void main(String args[]) {
        int n = 5;
        loop1(n);
        loop2(n);
    }

    public static void loop1(int n) {
        for (int i = 0; i < n; i++) {}
    }

    public static void loop2(int n) {
        for (int i = 0; i < n; ++i) {}
    }
}

Now compile it and disassemble it:

$ javac PostPre.java; javap -c PostPre.class 
Compiled from "PostPre.java"
public class PostPre {
  public PostPre();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
    Code:
       0: iconst_5      
       1: istore_1      
       2: iload_1       
       3: invokestatic  #2                  // Method loop1:(I)V
       6: iload_1       
       7: invokestatic  #3                  // Method loop2:(I)V
      10: return        

  public static void loop1(int);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: iload_0       
       4: if_icmpge     13
       7: iinc          1, 1
      10: goto          2
      13: return        

  public static void loop2(int);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: iload_0       
       4: if_icmpge     13
       7: iinc          1, 1
      10: goto          2
      13: return        
}

loop1() and loop2() have the same byte code.

查看更多
Ridiculous、
6楼-- · 2019-01-17 15:10

Try this in your environment

public class IsOptmized {
    public static void main(String[] args) {

        long foo; //make sure the value of i is used inside the loop
        long now = 0; 
        long prefix = 0;
        long postfix = 0;

        for (;;) {
            foo = 0;
            now = System.currentTimeMillis();
            for (int i = 0; i < 1000000000; i++) {
                foo += i;
            }
            postfix = System.currentTimeMillis() - now;

            foo = 0;
            now = System.currentTimeMillis();
            for (int i = 0; i < 1000000000; ++i) {
                foo += i;
            }
            prefix = System.currentTimeMillis() - now;

            System.out.println("i++ " + postfix + " ++i " + prefix + " foo " + foo);
        }
    }
}

Mine gives me

i++ 1690 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1600 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1611 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1691 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1600 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1691 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1691 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1692 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1691 ++i 1610 foo 499999999500000000

So even if it is not that much, I asume there is a difference

查看更多
Animai°情兽
7楼-- · 2019-01-17 15:12

For any reasonably capable optimizer, they will be exactly the same. If you aren't sure, look at the output bytecode or profile it.

查看更多
登录 后发表回答