私はEffectiveJavaを研究しており、本の項目5で、JoshuaBlochが不要なオブジェクトの作成の回避について説明しています。例は、値が計算された後は変更されない可変のDateオブジェクトを示しています。
ここで「悪い習慣」:
public Person(Date birthDate) {
this.birthDate = new Date(birthDate.getTime());
}
// DON'T DO THIS!
public boolean isBabyBoomer() {
// Unnecessary allocation of expensive object
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = gmtCal.getTime();
return birthDate.compareTo(boomStart) >= 0
&& birthDate.compareTo(boomEnd) < 0;
}
isBabyBoomerメソッドは、呼び出されるたびに、新しいCalendar、TimeZone、および2つのDateインスタンスを不必要に作成します。これは明らかに私には理にかなっています。
そしてここに改善されたコード:
public Person(Date birthDate) {
this.birthDate = new Date(birthDate.getTime());
}
/**
* The starting and ending dates of the baby boom.
*/
private static final Date BOOM_START;
private static final Date BOOM_END;
static {
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
}
public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0
&& birthDate.compareTo(BOOM_END) < 0;
}
Calendar、TimeZone、およびDateインスタンスは、初期化時に1回だけ作成されます。isBabyBoomer()
Blochは、メソッドが頻繁に呼び出されると、パフォーマンスが大幅に向上すると説明しています。
彼のマシン上:
悪いバージョン:1000万回の呼び出しで32,000ミリ秒
改善されたバージョン:1000万回の呼び出しで130ミリ秒
しかし、システムで例を実行すると、パフォーマンスはまったく同じです(14ms)。これは、インスタンスが1回だけ作成されるコンパイラ機能ですか?
編集:
これが私のベンチマークです:
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.set(1960, Calendar.JANUARY, 1, 1, 1, 0);
Person p = new Person(cal.getTime());
long startTime = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
p.isBabyBoomer();
}
long stopTime = System.nanoTime();
long elapsedTime = stopTime - startTime;
double mseconds = (double) elapsedTime / 1000000.0;
System.out.println(mseconds);
}
乾杯、マーカス