Help us understand the problem. What is going on with this article?

短絡評価って本当に処理が速いの? Javaにおける&&と&の違い

More than 1 year has passed since last update.

短絡評価とは

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サイトでは、&&の方が余分な評価をしないため処理が早いなどと書いてあります。その記述を読んだ時、私は疑問に思いました。「一応異なる処理なのだから、本当に右辺の処理をパスしただけで速くなるのだろうか?」
そこで私は実際に&&と&の処理速度の違いについて検証してみました。

検証用プログラム

短絡評価を行うプログラム

Test1
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文の条件式に&&が使われています。

短絡評価を行わないプログラム

Test2
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で&を使っても&&を使っても同じ結果になるという場合には、&&を使うことをお勧めします。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away