こんにちは。「Javaを復習する初心者」です。
4桁の自然数を年として与えらた時、うるう年であるか判定するという方法をJavaに用意されているAPIを使って実装してみました。以下の2つのパターンを作ってみました。
- Calendarクラスを利用する
- Time APIを利用する
Time APIはJava 8から新たに用意されたAPIです。
Calendarクラスで判定
最初にCalendarクラスを使って、うるう年を判定する方法を載せます。基本的な説明から書くので、面倒な場合はソースコードだけ見れば分かると思います。
Calendarクラスを使う場合、インスタンスを取得するという方式になっています。Calendarクラスには、getInstance()というstaticメソッドが用意されています。このメソッドはCalendarクラスのインスタンスを返却します。インスタンスを取得した後は、set()メソッドを呼び出して、日付を設定します。今回使うのはset(int year, int month, int date)です。
例えば、int型変数yearに4桁自然するが格納されているとします。[year]年2月1日のCalendarオブジェクトは以下のように作ります。
Calendarオブジェクトに2月を設定
// インスタンス取得
Calendar calendar = Calendar.getInstance();
// 日付を設定
calendar.set(year, Calendar.FEBRUARY, 1);
CalendarクラスにはgetActualMaximum(int field)というメソッドが用意されています。引数にはカレンダ・フィールドと呼ばれる値を指定します。Calendar.DATEという定数がこのメソッドのためのフィールド値で、月の日を示します。getActualMaximum(Calendar.DATE)と記述すれば、設定された月が何日あるかが返却されます。29日あれば、うるう年であると判定できます。
うるう年判定のためのメソッドは、例えば、以下のように実装出来ます。
Calendarクラスで判定
public static boolean judge(int year) {
// インスタンス取得
Calendar calendar = Calendar.getInstance();
// 日付を設定
calendar.set(year, Calendar.FEBRUARY, 1);
// 日数を取得
int numberOfdays = calendar.getActualMaximum(Calendar.DATE);
// 日数が29日の場合、trueを返却
return numberOfdays == 29;
}
以下のような使い方になります。
例
public static void main(String[] args) {
int year = 2016;
if (judge(year)) {
System.out.println(year + ": うるう年です。");
} else {
System.out.println(year + ": うるう年ではありません。");
}
year = 2017;
if (judge(year)) {
System.out.println(year + ": うるう年です。");
} else {
System.out.println(year + ": うるう年ではありません。");
}
結果
2016: うるう年です。
2017: うるう年ではありません。
Time APIで判定
Java 8以降のバージョンではTime APIが用意されています。ここでは、LocalDateクラスを使って判定する方法を載せます。
このクラスにはof(int year, int month, int dayOfMonth)というstaticメソッドが用意されています。引数で年、月、日を指定し、LocalDateのインスタンスが返却されます。
with(TemporalAdjuster adjuster)というメソッドが用意されていて、with(TemporalAdjusters.lastDayOfMonth())と記述すると、日にちが月末に設定されたLocalDateオブジェクトが返却されます。このオブジェクトに対して、getDayOfMonth()メソッドを呼び出せば、日数が取得できます。あとは29日なのかを判定するだけです。
例えば、次のように実装できます。
Time API
public static boolean judge(int year) {
// オブジェクト生成
LocalDate localDate = LocalDate.of(year, 2, 1);
// 日数を取得
int numberOfdays = localDate.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
// 日数が29日の場合、trueを返却
return numberOfdays == 29;
}
どちらの方法が速いのか
以下のプログラムで速さを比較してみました。
速さ比較
public class Test {
public static void main(String[] args) {
long start, end;
int year = 2000;
int max = 300000;
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
judgeByCalendar(year);
}
end = System.currentTimeMillis();
System.out.println("Calendar: " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
judgeByTimeAPI(year);
}
end = System.currentTimeMillis();
System.out.println("Time API: " + (end - start));
}
public static boolean judgeByCalendar(int year) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, Calendar.FEBRUARY, 1);
int numberOfdays = calendar.getActualMaximum(Calendar.DATE);
return numberOfdays == 29;
}
public static boolean judgeByTimeAPI(int year) {
LocalDate localDate = LocalDate.of(year, 2, 1);
int numberOfdays = localDate.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
return numberOfdays == 29;
}
}
結果
Calendar: 1125
Time API: 187
上記のようにTime APIを使った方が圧倒的に速いという結果になりました。Java 8以降ではTime APIを使った方が良いでしょう。