Stringと StringBuilder

みるくあいらんどっ! > ドキュメント > Java > じっくり学ぶ Java講座 [初心者向け・入門]


Stringを使用する上での問題

文字列、つまり String型インスタンスは、生成したが最後、永遠に値を変更できない、と説明しました。言い換えれば、文字列の内容を変更しようと思ったら新しい String型インスタンスが生成されます。ということは、文字列を段階的に作成すると、途中で無駄にたくさんのインスタンスが生成されてしまいます。繰り返し構文を使用する例として、サンプルプログラムを見ていきましょう。

ソースコードは以下の通り。

I201/I201.java

/**
 * abを 20回繰り返した文字列インスタンスを作成し、表示します。
 */
public class I201 {
	
	/**
	 * メインメソッド。
	 * @param args 引数
	 */
	public static void main(String[] args) {
		String s = "";
		
		for(int i = 0; i < 20; i ++) {
			s += "ab";
		}
		
		System.out.println(s);
	}
}

実行結果は以下の通り。

abababababababababababababababababababab

確かに、思うような文字列は生成されています。ところが、Javaのメモリ空間では以下のイメージのようにたくさんの String型インスタンスが生成されています。繰り返しの回数と同じ数だけ、newが実行されているということになります。

Stringと繰り返し

インスタンスの生成という処理は負担が大きいと言われます。今回はまだ繰り返しの回数が少なかったから良かったものの、この繰り返しの回数が増えていったら、重たいプログラムになってしまうかもしれません(なお、今時の Javaコンパイラはこのあたりを考慮しているため、気にしなくても問題ないようです)。

StringBuilderを使用する

Javaでは、内容を変更できる文字列を管理するためのクラスとしてStringBuilderクラスが用意されています。先のプログラムと同じ動作をするプログラムを、StringBuilderクラスを用いて実現してみます。

ソースコードは以下の通り。

I202/I202.java

/**
 * abを 20回繰り返した文字列インスタンスを作成し、表示します。
 * StringBuilderを使用します。
 */
public class I202 {
	
	/**
	 * メインメソッド。
	 * @param args 引数
	 */
	public static void main(String[] args) {
		StringBuilder s = new StringBuilder();
		
		for(int i = 0; i < 20; i ++) {
			s.append("ab");
		}
		
		// StringBuilderインスタンスから Stringインスタンスを生成
		String t = s.toString();
		
		System.out.println(t);
	}
}

実行結果は以下の通り。

abababababababababababababababababababab

実行結果は変わりませんが、イメージにすると大きな違いが分かると思います。

StringBuilderと繰り返し

見ての通り、StringBuilder型インスタンスは 1つだけ。その内容が変更されていることが分かります。このプログラムの場合、繰り返しの回数がどれだけ多くなろうとも、StringBuilder型インスタンスが 1個、String型インスタンスが 2個の合計 3個のインスタンスしか作られないことが分かります。

StringBuilderクラスのAPIとよく使用するメソッド

Java SE 7(Java 1.7)の StringBuilderクラスの説明書(API)を掲示しておきます→StringBuilderクラス

たくさんのインスタンスメソッドを利用することができます。その中でも特によく使うだろうと思われるものを以下にピックアップしました。

  • appendメソッド…文字列に新たな文字列などを追加します。
  • toStringメソッド…StringBuilderが持つ文字列を String型に変換したものを返します。

どちらのメソッドも、先ほどのソースコード内に登場していますね。

Stringと StringBuilder、StringBuffer

文字列を使用する場合には、基本的には Stringを使用して問題ありません。ほとんどの場合は、それで大丈夫です。

ただ、繰り返し構文などで文字列を連結していく場合などにおいて、あまりにも無駄なインスタンスが生成される場合には、StringBuilderの使用を考えてみても良いかもしれません。なお、StringBuilderと似たクラスに StringBufferというものがあります。StringBufferクラスのほうが歴史が古いですが、ほとんどは StringBuilderのほうがより適切です。ただし、マルチスレッドという特殊な場合においては、StringBufferを使用しなければならない場合があります。

最終更新: 2014/08/20 , 公開: 2013/02/08
▲top