在 for 循环条件下重复调用 getter
Repeatedly calling getter in for-loop condition
哪个循环更快,有区别吗?
final int cSize = getSize();
for(lineCount = 0; lineCount <= cSize; lineCount++) {
// Do something!
}
或
for(lineCount = 0; linecount <= getSize(); lineCount++) {
// Do something!
}
其中 getSize()
是一个简单的 getter:
private int getSize() {
return this.size;
}
假设this.size
是不是最终的,这两个循环有不同的语义:
- 第一个循环不会对循环内完成的
size
中的更改做出反应;它将根据 cSize
变量的要求执行多次。
- 第二个循环将对
size
的更改做出反应。如果 size
增加或减少,循环迭代次数也会增加或减少。
就性能而言,Java 的即时编译器足够聪明,可以直接使用 this.size
变量,有效地绕过 getter。这会产生非常相同的性能。
使用此示例测试不同的 for 循环:
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class ForLoopPerformanceTest {
private static List<Integer> list = new ArrayList<>();
private static long startTime;
private static long endTime;
static {
for (int i = 0; i < 1_00_00_000; i++) {
list.add(i);
}
}
@SuppressWarnings("unused")
public static void main(String[] args) {
// Type 1
startTime = Calendar.getInstance().getTimeInMillis();
for (Integer i : list) {
//
}
endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("For each loop :: " + (endTime - startTime) + " ms");
// Type 2
startTime = Calendar.getInstance().getTimeInMillis();
for (int j = 0; j < list.size(); j++) {
//
}
endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("Using collection.size() :: " + (endTime - startTime) + " ms");
// Type 3
startTime = Calendar.getInstance().getTimeInMillis();
int size = list.size();
for (int j = 0; j < size; j++) {
// System.out.println(j);
}
endTime = Calendar.getInstance().getTimeInMillis();
System.out.println(
"Using [int size = list.size(); int j = 0; j < size ; j++] :: " + (endTime - startTime) + " ms");
// Type 4
startTime = Calendar.getInstance().getTimeInMillis();
for (int j = list.size(); j > size; j--) {
// System.out.println(j);
}
endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("Using [int j = list.size(); j > size ; j--] :: " + (endTime - startTime) + " ms");
}
}
The Results
对于每个循环:: 108 毫秒
使用 collection.size() :: 39 毫秒
使用[int size = list.size();整数 j = 0; j < 大小; j++] :: 4 毫秒
使用[int j = list.size(); j > 大小; j--] :: 0 毫秒
哪个循环更快,有区别吗?
final int cSize = getSize();
for(lineCount = 0; lineCount <= cSize; lineCount++) {
// Do something!
}
或
for(lineCount = 0; linecount <= getSize(); lineCount++) {
// Do something!
}
其中 getSize()
是一个简单的 getter:
private int getSize() {
return this.size;
}
假设this.size
是不是最终的,这两个循环有不同的语义:
- 第一个循环不会对循环内完成的
size
中的更改做出反应;它将根据cSize
变量的要求执行多次。 - 第二个循环将对
size
的更改做出反应。如果size
增加或减少,循环迭代次数也会增加或减少。
就性能而言,Java 的即时编译器足够聪明,可以直接使用 this.size
变量,有效地绕过 getter。这会产生非常相同的性能。
使用此示例测试不同的 for 循环:
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class ForLoopPerformanceTest {
private static List<Integer> list = new ArrayList<>();
private static long startTime;
private static long endTime;
static {
for (int i = 0; i < 1_00_00_000; i++) {
list.add(i);
}
}
@SuppressWarnings("unused")
public static void main(String[] args) {
// Type 1
startTime = Calendar.getInstance().getTimeInMillis();
for (Integer i : list) {
//
}
endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("For each loop :: " + (endTime - startTime) + " ms");
// Type 2
startTime = Calendar.getInstance().getTimeInMillis();
for (int j = 0; j < list.size(); j++) {
//
}
endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("Using collection.size() :: " + (endTime - startTime) + " ms");
// Type 3
startTime = Calendar.getInstance().getTimeInMillis();
int size = list.size();
for (int j = 0; j < size; j++) {
// System.out.println(j);
}
endTime = Calendar.getInstance().getTimeInMillis();
System.out.println(
"Using [int size = list.size(); int j = 0; j < size ; j++] :: " + (endTime - startTime) + " ms");
// Type 4
startTime = Calendar.getInstance().getTimeInMillis();
for (int j = list.size(); j > size; j--) {
// System.out.println(j);
}
endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("Using [int j = list.size(); j > size ; j--] :: " + (endTime - startTime) + " ms");
}
}
The Results
对于每个循环:: 108 毫秒
使用 collection.size() :: 39 毫秒
使用[int size = list.size();整数 j = 0; j < 大小; j++] :: 4 毫秒
使用[int j = list.size(); j > 大小; j--] :: 0 毫秒