スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


--------------------------------------------------------------------------------------

メモ・・・ループ内でStringを+で連結するとFindBugsで警告される話

javaでループ処理内で文字列を連結させていく場面が出てくるときがあります。
そのとき、単純に+で文字列連結するとFindBugsで警告がでるときがあります。
 
ちょっと簡単に以下のようなソースを入れると警告がでます。

        String str = "";
        for (int i = 0; i < 10000; i++) {
            str += Integer.toString(i);
        }


---------------------------------------------------------
Pattern: このメソッド内で、+を使ってループ内で文字列を連結しています。
id: SBSC_USE_STRINGBUFFER_CONCATENATION, type: SBSC, category: PERFORMANCE

このメソッドの中で、ループ内でStringの連結を繰り返しているようです。このためStringBuffer/StringBuilderへの変換、連結、そしてStringへの再変換という処理が何度も繰り返されます。文字列が毎回コピーし直されて長くなっていくため、繰り返し回数の二乗の処理コストが必要となる場合があります。

明示的にStringBufferあるいはStringBuilder(J2SE 1.5から導入されます)を用いる事で、パフォーマンスを改善する事が出来ます。

例)


// 悪い例

String s = "";

for (int i = 0; i < field.length; ++i) {

s = s + field[i];

}



// 良い例

StringBuffer buf = new StringBuffer();

for (int i = 0; i < field.length; ++i) {

buf.append(field[i]);

}

String s = buf.toString();

---------------------------------------------------------

これはSJC-Pの取得で勉強したときにも、参考書に記述されていたのですが、
そんなに実行速度が変わるのか疑問でした。
というわけで、ちょっと測ってみたいと思います。


実測方法はjava.lang.ObjectのnanoTime()メソッドの説明に記述されている方法を使用して、
5回実行してその平均を求めてみます。



まずは普通に文字列連結した場合。

package main;

import bean.HogeBean;

public class TestHoge {

    public static void main(String[] args) {

        long startTime = System.nanoTime();

        String str = "";
        for (int i = 0; i < 10000; i++) {
            str += Integer.toString(i);
        }

        long estimatedTime = System.nanoTime() - startTime;
        System.out.println("estimatedTime = " + estimatedTime);

    }

}


これを5回実行してみると
---------------------------------------------------------
estimatedTime = 1330430863
estimatedTime = 1325961511
estimatedTime = 1326294489
estimatedTime = 1391642798
estimatedTime = 1333323965
---------------------------------------------------------
となりまして、平均1341530725.2(ナノ秒)。
ナノ秒ってわかりづらいですね。
単位を変えると、
1341530.7(マイクロ秒)
1341.5(ミリ秒)
ってことですね。

さて、次にFindbugsの例にあるようにStringBufferを使用して以下のようなソースを実測してみます。

package main;

import bean.HogeBean;

public class TestHoge {

    public static void main(String[] args) {

        long startTime = System.nanoTime();

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 10000; i++) {
            sb.append(Integer.toString(i));
        }

        long estimatedTime = System.nanoTime() - startTime;
        System.out.println("estimatedTime = " + estimatedTime);

    }

}


これを5回実行してみると
---------------------------------------------------------
estimatedTime = 9043554
estimatedTime = 8992905
estimatedTime = 9728598
estimatedTime = 8811576
estimatedTime = 9466551
---------------------------------------------------------
となりまして、平均9208636.8(ナノ秒)
9208.6(マイクロ秒)
9.2(ミリ秒)

当方のパソコンの環境では10000回の単純な繰り返しで1秒も速度が変わることがわかりました。
これはかなり実行速度が変わったといっていいでしょうね。

なお、StringBufferとなっているところをStirngBuilderで連結するほうがさらに早くなるそうで、実測してみると
---------------------------------------------------------
estimatedTime = 7911682
estimatedTime = 8961621
estimatedTime = 8341625
estimatedTime = 8887203
estimatedTime = 8400948
---------------------------------------------------------
平均8500615.8(ナノ秒)
8500.6(マイクロ秒)
8.5(ミリ秒)

となりました。
StringBufferとStirngBuilderの違いはAPI参照してください。


追記)
比較するプログラム内容がちょっとおかしいような気がしますが・・・修正が面倒なのでこのままにしておきます。
関連記事


--------------------------------------------------------------------------------------

コメントの投稿

非公開コメント

このブログについて
  • 全記事一覧(時間順)
  • このブログについて
  • 私のプロフィール
  • 当ブログで扱っている動画について
  • 記事違いなコメントのお返事

  • カテゴリー
    twitter
    カレンダー
    10 | 2017/11 | 12
    - - - 1 2 3 4
    5 6 7 8 9 10 11
    12 13 14 15 16 17 18
    19 20 21 22 23 24 25
    26 27 28 29 30 - -
    Amazon
    でたらめな当ブログにぴったりな商品を自動で表示するみたいです。



    月別アーカイブ
    プロフィール

    たづみ

    Author:たづみ
    ・1981年生まれの男
    ・もう少し詳細なプロフィールはこちらで

    最新コメント
    アクセスランキング
    [ジャンルランキング]
    日記
    773位
    アクセスランキングを見る>>

    [サブジャンルランキング]
    会社員・OL
    171位
    アクセスランキングを見る>>


    上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。