空文字判定の高速化

2010年04月10日 15時07分 Java



※対象バージョン:Java1.4

大学や専門学校ではこういうことを教えない・・・と思います、空文字の高速判定についてです。変数の文字列が空文字か否かを判定する場合に equals() メソッドを利用するのが一般的です。しかし equals() による空文字の判定は予想以上に無駄なのです。

// 空文字の比較
String str = "文字列";
if ( "".equals(str) ) { // str が "" と一致するかを判定
    // 空文字の処理
}

// Java1.4 の String クラスの equals() メソッドの実装
// java.lang.String#equals
public boolean equals(Object anObject) {
    if (this == anObject) {
       return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = count;
        if (n == anotherString.count) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = offset;
            int j = anotherString.offset;
            while (n-- != 0) {
                if (v1[i++] != v2[j++])
                    return false;
            }
            return true;
        }
    }
    return false;
}

/******* equals 処理内容 *************************************************************
 * 1. オブジェクトが一致していることの確認します。
 *    文字列の一致の判定という意味では通常はありえません。
 * 2. equals() の文字列と引数に指定した文字列を文字 (char) 単位に分割します。
 * 3. 1 文字ずつ比較し、一致しない場合に false を返します。
 * 4. 処理が最後まで進んだときに、完全一致と判定され、true を返します。
**************************************************************************************/

 
ソースコードを見ての通りですが String クラスの equals() メソッドの判定は空文字の判定に向いておりません。また判定する際に判定文字列のオブジェクトを生成していたりすると処理の時間が増えます。

空文字を判定する方法は equals() にもあります。length() メソッドを使い、文字列の長さを比較する方法です。length() の処理を見ると処理の単純さは一目瞭然です。

// 空文字の比較
String str = "文字列";
if ( str!= null && str.length() == 0 ) {
    // 空文字の処理
}

// Java1.4 の String クラスの length() メソッドの実装
// java.lang.String#length
public int length() {
    return count;
}

/******* length 処理内容 *************************************************************
 * 1. 保持する文字数のカウントを取得します。
**************************************************************************************/

 
実際に equals() と length() を実際に比較してみます。

// "" と "test" の文字列で 1000 万回の空文字判定を行います。
public class time{

    public static void main(String[] args){
        
        long start, stop, diff;

        String a = "";
        String b = "test";
        int num = 10000000;

        // "" を 1000 万回の length() による空文字判定
        start = System.currentTimeMillis();
        for(int i = 0; i < num; i++){
            if(a.length() < 1){
            }
        }
        stop = System.currentTimeMillis();
        diff = stop - start;
        System.out.println(a + ".length() < 1 : " + diff + "ms");

        // "test" を 1000 万回の length() による空文字判定
        start = System.currentTimeMillis();
        for(int i = 0; i < num; i++){
            if(b.length() < 1){
            }
        }
        stop = System.currentTimeMillis();
        diff = stop - start;
        System.out.println(b + ".length() < 1 : " + diff + "ms");

        // "" を 1000 万回の equals() による空文字判定
        start = System.currentTimeMillis();
        for(int i = 0; i < num; i++){
            if(a.equals("")){
            }
        }
        stop = System.currentTimeMillis();
        diff = stop - start;
        System.out.println(a + ".equals(\"\") : " + diff + "ms");

        // "test" を 1000 万回の equals() による空文字判定
        start = System.currentTimeMillis();
        for(int i = 0; i < num; i++){
            if(b.equals("")){
            }
        }
        stop = System.currentTimeMillis();
        diff = stop - start;
        System.out.println(b + ".equals(\"\")  : " + diff + "ms");

    }
}

/******* プログラム実行環境 **********************************************************
 * OS:     CentOS 4.3
 * Java:   1.4.2_11
 * CPU:    Pentium3 800MHz
 * Memory: 256MB
**************************************************************************************/

/******* プログラム実行結果 **********************************************************
 * .length() < 1 : 92ms
 * test.length() < 1 : 77ms
 * .equals("") : 364ms
 * test.equals("") : 401ms
**************************************************************************************/

 
実行結果を見ると実行時間にかなり大きな差がついていることがわかります。夜間バッチや多くのリクエストのある Web システム(SOA を利用したシステムなど)と多くの空文字判定の処理を繰り返すようなシステムでは length() を利用して空文字判定をさせたほうが利口であると言えます。
 

String
boolean equals (Object anObject)
          この文字列と指定されたオブジェクトを比較します。
int length ()
          この文字列の長さを返します。


Leave a Reply

preload preload preload