Using new Date().getTime()
gives the wall clock time. But it is really not what we as developers want (most of the time, until doing some benchmarking where enterprise level benchmarking are used) because wall clock time is effected by many back ground processes, so to counter that Java provides more sophisticated API for measuring the time.
To exclude the effects of other system activity, you need to measure application "User time" instead.
- "User time" is the time spent running your application's own code.
- "CPU time" is user time plus system time. It's the total time spent using a CPU for your application.
Below example to demonstrate CPU and User time calculation using ManagementFactory.getThreadMXBean()
API.
Thread thread = new Thread(){
public void run() {
for (int i = 0; i < 100000; ++i) {
int result = 0;
for (int j = 0; j < i + 1; ++j) {
result += j;
}
}
System.out.println("FOR approach: ThreadCpuTime = " + ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime()/1000000000d);
System.out.println("FOR approach: UserTime = " + ManagementFactory.getThreadMXBean().getCurrentThreadUserTime()/1000000000d);
};
};
thread.start();
Thread thread2 = new Thread(){
public void run() {
for (int i = 0; i < 100000; ++i) {
int result = 0;
int j = 0;
while (j < i + 1) {
result += j++;
}
}
System.out.println("WHILE approach: ThreadCpuTime = " + ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime()/1000000000d);
System.out.println("WHILE approach: UserTime = " + ManagementFactory.getThreadMXBean().getCurrentThreadUserTime()/1000000000d);
};
};
thread2.start();
Having said, I am really not sure why you are getting unexpected behavior, I ran your code both in Eclipse and IntelliJ IDE, and I always got FOR loop approach as faster than WHILE loop.
Probably try to restart you Eclipse and have lesser number of background processes running OR do not run it Eclipse but run the tests from Java command line so that you can sure of results.
As can be seen from below Byte Code Analysis that WHILE and FOR loop approach has same bytes codes generated, which means there would be same assemble code and hence same time CPU will take to execute instructions.
But practically when we run in your IDE or other wise, then is being effect by background processes, so different times are observed. But in this particular case - WHILE v/s FOR, it is more appropriate to do byte code analysis and conclude that WHILE and FOR loop approaches will take same time.
Byte code of FOR loop:
{
public Test2();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 21
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_1
12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
15: iinc 1, 1
18: goto 2
21: return
LineNumberTable:
line 3: 0
line 4: 8
line 3: 15
line 6: 21
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 2
locals = [ int ]
frame_type = 250 /* chop */
offset_delta = 18
}
Byte code of WHILE loop:
{
public Test();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 21
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_1
12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
15: iinc 1, 1
18: goto 2
21: return
LineNumberTable:
line 3: 0
line 4: 2
line 5: 8
line 6: 15
line 8: 21
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 2
locals = [ int ]
frame_type = 18 /* same */
}
Further reading: