短絡評価とは
Javaを少し勉強すると「短絡評価」というものが出てきます。これは&&や||といった論理演算子において、左辺を評価した時点で、式全体の真偽値が決定し右辺を評価する必要がない場合、右辺を評価しないという機能のことです。
次の例をみてください。
boolean flag1 = false;
boolean flag2 = false;
if(flag1 && flag2){
System.out.println("2つの変数はどちらもtrueです。");
}
このプログラムでは3行目の条件分岐で中括弧のブロック内が実行されるためには、flag1,flag2がともにtrueでなければなりません。今回はflag1がfalseであるため、flag2の真偽値を確かめるまでもなく中括弧のブロック内を行う必要がないことがわかります。このような状況で、自動でflag2の評価は行わないようにしてくれる機能が短絡評価です。
#&&と&の違い
Javaには&&と&という二つの似た演算子があります。この二つの演算子はほとんど同じような機能を持つのですが、少し異なる部分があります。
先ほど述べたように&&という演算子は短絡評価の機能が働きます。しかし、&には短絡評価が働きません。すなわち、&は右辺の値を評価する必要がない状況でも右辺の値を評価するのです。
#本当に短絡評価は処理が早いのか?
Javaの参考書やWebサイトでは、&&の方が余分な評価をしないため処理が早いなどと書いてあります。その記述を読んだ時、私は疑問に思いました。「一応異なる処理なのだから、本当に右辺の処理をパスしただけで速くなるのだろうか?」
そこで私は実際に&&と&の処理速度の違いについて検証してみました。
検証用プログラム
短絡評価を行うプログラム
long start = System.currentTimeMillis();
boolean flag1 = false;
boolean flag2 = false;
for(long i=0; i<10000000000l; i++) {
if(flag1 && flag2) {
System.out.print("");
}
}
long end = System.currentTimeMillis();
System.out.println("実行時間" + (end - start) + "ms");
if文の条件式に&&が使われています。
短絡評価を行わないプログラム
long start = System.currentTimeMillis();
boolean flag1 = false;
boolean flag2 = false;
for(long i=0; i<10000000000l; i++) {
if(flag1 & flag2) {
System.out.println("");
}
}
long end = System.currentTimeMillis();
System.out.println("実行時間" + (end - start) + "ms");
if分の条件式に&が使われています。
検証結果
実際に上記の2種類のプログラムを走らせてそれぞれのプログラムの実行時間の統計を撮ってみました。以下の表がその結果です。
プログラムの実行時間(単位:ms)
短絡評価あり(&&) | 短絡評価なし(&) | |
---|---|---|
1回目 | 3546 | 3500 |
2回目 | 3556 | 3595 |
3回目 | 3586 | 3565 |
4回目 | 3574 | 3564 |
5回目 | 3552 | 3636 |
6回目 | 3570 | 3620 |
7回目 | 3512 | 3568 |
8回目 | 3563 | 3597 |
9回目 | 3560 | 3565 |
10回目 | 3555 | 3500 |
平均 | 3557.6 | 3571.0 |
表の平均を見る限り、短絡評価を行なっている方が処理速度が速いと考えられます。しかし、今回の実験では標本数が少なく、短絡評価ありと短絡評価なしの実行時間の差は小さいものであったので、短絡評価なしの&より短絡評価ありの&&を利用した方が処理が速くなると結論づけるには少し根拠が弱いです。
まとめ
今回私が行なった実験では短絡評価を利用した方が処理が速くなるという結果が得られました。とりあえず、Javaで複数の真偽値の論理積を取る場面では、&&を使う方が良いと考えられます。また、C言語などの他の言語では、&が両辺を2進数と見て各桁について論理積をとるという全く雰囲気の異なる機能となっている場合もあるので、言語を乗り換えた際にミスが増えないようにする意味でも、Javaで&を使っても&&を使っても同じ結果になるという場合には、&&を使うことをお勧めします。