忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

文字列の連結をStringBuilderで高速に行う(StringBuilder)

文字列の連結は、簡単な文字列の場合には(アンド)演算子を用いて行います。 この演算子は二項演算子の様に文字列の連結に使えますし、代入演算子的にも使用できます。 例としては、以下の様な感じです。

    Dim strData as String = "ABC"
    '二項演算子の様に文字列連結
    strData = strData & "DEF"
    '代入演算子の様に文字列連結
    strData &= "HIJKLMN"

(アンド)演算子も使い方が簡単なので、特に速度を必要としない場合にはそのままで特に問題はありません。 この String 型データはそれ自身がオブジェクトであり、中身を変更できない様になっています。 つまり上の二項演算子の例では、「strData」に代入している様な形ですが、
内部的には「strData」の実体は最初の「strData」が持っていた文字列(オブジェクト)と連結したものを 新しいオブジェクトとして作成されます。 では最初の文字列(オブジェクト)はどうなるかと言いますと、システム的には使われないオブジェクトとして 廃棄される状態になります。 実際の廃棄はシステムが勝手に行いますので、心配はいらないのですが、この連結が行われると、どんどん内部的に 使われないオブジェクトが生成されてしまいます。

そこで、この欠点を補うのが StringBuilder クラスです。 StringBuilder は文字列のオブジェクトとしては1個のみ存在し、 そのオブジェクトに対して追加、削除、置換を行いますので上記の様な無駄なオブジェクが生成されずに 処理速度が向上します。
以下の例は、(アンド)演算子を使った場合と、StringBuilder クラスを使った簡単な例を示します。

文字列の連結の簡単な例

    '少ない文字列の連結例
    Private Sub BtnStringAdd_Click(sender As Object, e As EventArgs) Handles BtnStringAdd.Click
        Console.WriteLine("...BtnStringAdd_Click")
        '===[&]を使った文字列の連結===
        Dim strData As String = ""
        '数値0~9を"0"~"9"として追加連結(10回分の連結)
        For i As Integer = 0 To 9
            strData = strData & i.ToString
        Next
        '文字列の左に付加
        strData = "文字列:" & strData
        '表示
        Console.WriteLine("[&]の連結:{0}/", strData)

        '===[StringBuilder]を使った文字列の連結===
        Dim sbData As New System.Text.StringBuilder()
        '数値0~9を"0"~"9"として追加連結
        For i As Integer = 0 To 9
            sbData.Append(i.ToString)
        Next
        '表示
        Console.WriteLine("[StringBuilder]の連結:{0}/", sbData.ToString())
    End Sub

StringBuilder を使って速度がどの位向上するのかを例として以下に示します。 以下にそのソースを示します。

文字列の連結をStringBuilderで高速に行う

    '回数の多い文字列の連結例
    Private Sub BtnStringAddBig_Click(sender As Object, e As EventArgs) Handles BtnStringAddBig.Click
        Console.WriteLine("...BtnStringAddBig_Click")
        '文字列の宣言
        Dim strData As String = ""
        '開始時刻
        Dim tc As Integer = System.Environment.TickCount
        For i As Integer = 0 To 9
            '数値0~9を"0"~"9"として10000回追加
            For ii As Integer = 1 To 10000
                strData = strData & i.ToString
            Next
        Next
        '処理時間表示(結果文字列は大きすぎるので表示しない)
        Console.WriteLine("処理時間:{0}ミリ秒", System.Environment.TickCount - tc)

        '文字列の宣言
        Dim sbData As New System.Text.StringBuilder()
        tc = System.Environment.TickCount
        For i As Integer = 0 To 9
            '数値0~9を"0"~"9"として10000回追加
            For ii As Integer = 1 To 10000
                sbData.Append(i.ToString)
            Next
        Next
        '処理時間表示(結果文字列は大きすぎるので表示しない)
        Console.WriteLine("処理時間:{0}ミリ秒", System.Environment.TickCount - tc)
    End Sub


結果は一目瞭然なのですが、実行時間として100倍ぐらい違います。 処理としては簡単な1万回の連結を10回のループで回していますが、結果的には10万回の文字列連結になりますので では10万回の String オブジェクト生成が行われるので、時間が掛かる様です。

PR

コメント

コメントを書く