- PR -

StringBuilderの使い方について。

投稿者投稿内容
DT
常連さん
会議室デビュー日: 2003/05/06
投稿数: 31
投稿日時: 2003-11-08 13:05
ご教示願います。
文字列連結において、StringBuilderを使用した方が高速である…
と説明されています。
うまく説明出来ないのですが、以下の様なコードの場合、

Dim sb As New StringBuilder
Dim st As String

For i = 0 To 10000
For x = 0 To 2000
sb.Append("TESTTEST")
Next
st = sb.ToString()
Next

上記でst = sb.ToString()の後、
sbを初期化したい場合、
自分は、sb.Replace(sb.ToString(), Nothing)と書いてますが
一般的には他にどの様な方法があるのでしょうか?

データベースから拾ってきたデータをループして加工する際、
文字列連結でこのStringBuilderが使えるな、と思ったのですが、
初期化方法がよく分からなくて…単純にループ内冒頭で
StringBuilderを定義するのがイイのでしょうか…?

分かりにくい文章で申し訳ありませんが、どなたかご指導お願いします。
mei
大ベテラン
会議室デビュー日: 2003/04/08
投稿数: 114
投稿日時: 2003-11-08 13:14
sb.Length = 0
とか、どうでしょうか?
DT
常連さん
会議室デビュー日: 2003/05/06
投稿数: 31
投稿日時: 2003-11-08 13:36
mei様、ご回答ありがとうございます。

sb.Length = 0 にすると、このインスタンスの長さが0になり、
sb.Remove(0, sb.Length) にすると、
現在のインスタンスの文字列値が length だけ短縮されます。容量には影響ありません。
との事です。
すみません、根本的な事が理解出来ていないのですが、
ループ処理等で使うにはどちらがベターなのでしょうか?
dai
ベテラン
会議室デビュー日: 2001/08/28
投稿数: 85
投稿日時: 2003-11-08 14:53
> sbを初期化したい場合、
> 自分は、sb.Replace(sb.ToString(), Nothing)と書いてますが
> 一般的には他にどの様な方法があるのでしょうか?

僕の場合、普通に、
[C#]
sb = new StringBuilder();

と初期化します。

メモリが気になるのであれば、参照カウンタを減らし(Nothing を代入し)て、
GC.Collect(); します。
mei
大ベテラン
会議室デビュー日: 2003/04/08
投稿数: 114
投稿日時: 2003-11-09 00:12
引用:

DTさんの書き込み (2003-11-08 13:36) より:
すみません、根本的な事が理解出来ていないのですが、
ループ処理等で使うにはどちらがベターなのでしょうか?


速度の面から見た場合、オブジェクトのnewを頻繁に行うのは好ましくありません。
それと、メモリのアロケートもコストがかかります。
なので、作業用のStringBuilderをループの外で作成するのが良いと思います。
あと、文字列の最大長が分かっている場合は、
StringBuilderのキャパシティも指定した方が良いかも知れません。
# 文字列の長さのばらつきが極端にあったりすると話は変わってきますが・・・

・初期化方法
パフォーマンスを測ってないので何ともいえませんが、
Length = 0だと、恐らく内部の長さ管理変数を0にするだけだと思うので、
処理が軽いと予想します。

・おまけ
str = GetStr1() + GetStr2() + GetStr3() + ...;
↑こういう場合は、StringBuilderよりも上記のように羅列した方が速いです。
#ちょっと意外で驚きました・・・
Izumi, Y.
ベテラン
会議室デビュー日: 2002/03/19
投稿数: 77
お住まい・勤務地: 東京
投稿日時: 2003-11-09 15:01
長さ(Length プロパティ)と容量(Capacity プロパティ)は別物です。StringBuilder ではあらかじめある程度の領域を確保しておき(「あらかじめ」というのは語弊があるかもしれませんが)、その領域に文字列を保存します。Capacity プロパティはその領域の大きさ(容量)を表します。Length プロパティは保存している文字列の実際の長さです。
DT
常連さん
会議室デビュー日: 2003/05/06
投稿数: 31
投稿日時: 2003-11-09 17:52
dai様、mei様、IZUMI様ご回答有難うございます。

そうですね…やはり作業用のStringBuilderは、ループの外で
作成しようと思います。
肝心の初期化方法については、RemoveとLengthとで簡単なサンプルを
作成してテストしてみるのが一番ですね…。
ただ対象がASP.NETなので、まずはWindows Formでテストしてみます。
あとIZUMI様のお話ですと、やはりRemoveよりもLength = 0と記述した
方が効率的という事でしょうか?
DT
常連さん
会議室デビュー日: 2003/05/06
投稿数: 31
投稿日時: 2003-11-09 22:50
自宅PC(OS:Windows2000 SP4)にVS.NET2002が入っていたのを
思い出しまして、簡単なコンソールアプリでテストしてみました。

sTime = Now

Dim x As Int32
Dim y As Int32
Dim sb1 As New StringBuilder()
Dim st1 As String

For x = 0 To 5000
For y = 0 To 5000
sb1.Append("Test")
Next
st1 = sb1.ToString()
sb1.Length = 0
Next

eTime = Now
Console.WriteLine("String Builder No1 " & eTime.Subtract(sTime).TotalSeconds & " seconds.")

sTime = Now

Dim xx As Int32
Dim yy As Int32
Dim sb2 As New StringBuilder()
Dim st2 As String

For xx = 0 To 5000
For yy = 0 To 5000
sb2.Append("Test")
Next
st2 = sb2.ToString()
sb2.Remove(0, sb2.Length)
Next

eTime = Now
Console.WriteLine("String Builder No2 " & eTime.Subtract(sTime).TotalSeconds & " seconds.")

sTime = Now

Dim xxx As Int32
Dim yyy As Int32
Dim sb3 As New StringBuilder()
Dim st3 As String

For xxx = 0 To 5000
For yyy = 0 To 5000
sb3.Append("Test")
Next
st3 = sb3.ToString()
sb3.Replace(sb3.ToString(), Nothing)
Next

eTime = Now
Console.WriteLine("String Builder No3 " & eTime.Subtract(sTime).TotalSeconds & " seconds.")


結果ですが、
No1 (Length = 0)が、8.4421392 seconds.
No2 (Remove)が、8.2017396 seconds.
No3 (Replace)が、9.113104 seconds.
という結果でした。
何度か実行してみましたが、No2 , No1 , No3 という順序は
変更ありませんでした。

スキルアップ/キャリアアップ(JOB@IT)