検索

キーワード


【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

  • 公開日:2020-07-31 18:18:13
  • 最終更新日:2021-01-25 11:01:22
【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

こんにちは。新人エンジニアのサトウです。

システムエンジニアとして駆け出したばかりですが、

初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。


プログラム初心者にも✅、プログラムに興味がある人✨も、

短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!

文字列を扱う3つのクラス【java.langパッケージ】

java.langパッケージの文字列を扱うクラスには

Stringクラス、StringBufferクラス、StringBuilderクラスの3つがあります。


Stringクラスについては以下リンクの記事で紹介しています。

参考記事リンク:【Java】Stringクラスの文字列比較・判定・検索

        【Java】StringBufferクラスとStringBuilderクラスの文字列操作

        【Java】MessageFormatクラスでの文字列置換

        【Java】Stringクラスformatメソッドの文字列整形とエスケープシーケンス

        【Java】Java8 以降に追加された文字列結合(StringクラスjoinメソッドとStringjonerクラス)

        【Java】"サロゲートペア"を包含する文字列の操作

        【Java】文字列・正規表現


- StringBuilderクラスとStringBufferクラスを知ろう

なぜ、これらのクラスが用意されているのでしょうか。


Stringクラスとの最大の違いは、変数に格納した文字列を変更できる点です。

Stringクラスでは、変数に文字列を格納した後は変更できません。

しかし、StringBuilderクラス(以下Builderクラスと呼ぶ)とStringBufferクラス(以下Bufferクラスと呼ぶ)は

変数に文字列を格納した後でも文字列の内容や長さを特定のメソッドの呼出しにより変更可能になっています。


Stringクラスでも+(プラス)演算子やconcatメソッドを使うことで文字列の連結が可能です。

しかし、連結の際に毎回新しいオブジェクトを生成することになるため

処理コストが高く処理に時間がかかる場合があります。

Builderクラス、Bufferクラスでの文字列操作は、新しいオブジェクトの生成は行わず、

バッファ内(データの保存場所)で文字列を操作するためStringクラスよりも処理コストが低くなります。

(繰り返し処理などで、文字列の連結が複数回行われる場合などは、処理速度の差が顕著になります。)


これら2つのクラスは、可変な文字列に対応するために用意されているということです!

StringBufferクラスがjava1.0で導入され、StringBuilderクラスはJava1.5で導入されました。


- 二つのクラスの違いを知ろう

Javadocでは以下のように説明があります。


StringBuffer スレッドセーフな可変の文字列です。

StringBuilder 文字の可変シーケンスです。

スレッドセーフ thread safety 参照:javadoc-StringBuilder/javadoc-StringBuffer
あるコンピュータプログラムを複数のスレッドで並行して実行していても、問題が生じない仕様や設計になっていること。


つまり、Bufferクラスはマルチスレッド(並列処理)に対応したクラス、

Builderクラスはシングルスレッド(直列処理)に適したクラスということになります。


複数のスレッドで使用する際にBufferクラスは安全に使用することができます。

一方で複数の処理を並行して進めることが必要がない場合、Bufferクラスのままでは不必要な処理コストがかかってしまいます。


このようなシングルスレッド(直列処理)の場合はBuilderクラスを使う方が適しています。





基本的な操作について

今回の記事で紹介する操作はBuilderクラス、Bufferクラスのどちらでも使用することができます。

- 初期化と代入について

StringBuilder変数名= new StringBuilder()

StringBuffer 変数名= new StringBuffer()


両者のクラスも同じように初期化(インスタンス化)を行えます。

初期容量が16文字である空の文字列ビルダーを構築します。


初期化の際に引数を以下のように指定することもできます。

String:指定された文字列の内容に初期化された文字列ビルダーを構築します。

int:capacity引数によって指定された初期容量がある空の文字列ビルダーを構築します。

StringBuilder変数名= new StringBuilder(String str)
StringBuilder変数名= new StringBuilder(int capacity)

※Bufferも同様です。


この記事では、基本的な操作のappendメソッド・insertメソッドに加えて、その他の操作もいくつか紹介します。


append:文字列の連結、追加などの処理を行う時に使います。

insert:同じ文字列に対して挿入を行う場合に使います。

delete:指定した範囲の文字列を削除する操作です。

replace:指定した範囲に文字列を置き換えられる操作です。

reverse:文字列の順序を逆に置き換えられる操作です。

substring:文字列内のある部分だけを使用したときに使います。

indexOf:文字列内のある部分の最初のインデックスを知りたい時に使います。

Stringオブジェクトの生成法:StringBuilder・StringBufferオブジェクトをStringオブジェクトに変更する操作です。


今回はすべてBuilderクラスを利用した紹介になります。


- appendメソッド

StringBuilder append(String str)

引数のデータをStringBuilder文字列に追加できます。

引数には様々な種類のデータを受け取ることができるようにオーバーロードされています。

【boolean char char[] double float int long Object String StringBuffer】


Stringクラスでも「+」(プラス演算子)や「concatメソッド」を使って文字列の連結が可能です。

しかし毎回新しいインスタンスを生成することになるため、処理に時間が掛かってしまいます。

Builderクラス、Bufferクラスを使う事でこの問題を解決することができます。


以下の例ではString変数を追加しています。

public class Test {
	public static void main(String[ ] args) {

		StringBuilder s=new StringBuilder("名前は");

		s.append("サトウです。");

		System.out.println(s);
    }
}

出力結果

名前はサトウです。


Stringクラスを使用した連結の例と比較してみましょう。

public class Test {
	public static void main(String[ ] args) {
        String s="名前は";

		String t=s.concat("サトウです。");

		System.out.println(s);
		System.out.println(t);
    }
}

出力結果

名前は

名前はサトウです。

Stringクラスを利用すると、文字列を結合する度に新しいオブジェクトが生成されるため処理コストが高くなります。

Builderクラスは、Builderオブジェクト(変数s)を持つバッファ内で文字列を操作するため、

新しいオブジェクトを生成する必要がなく、処理コストを抑える事ができます。


上の例では少ない処理を扱っていますが、

膨大な処理の場合はBuilderクラスを利用した方が良いことがわかると思います!


Stringクラスの文字列連結は以下の記事で紹介しています。

参考:【Java】Stringクラスについての理解と基本的な文字列操作


- insertメソッド

StringBuilder insert(int offset, String str)

第一引数で指定した位置に、第二引数に指定したデータを挿入できます。

(offsetは「埋め合わせる」という意味で使われています。数値はインデックスの値を入れます。)

第二引数には様々な種類のデータを受け取ることができるようにオーバーロードされています。

【boolean char char[] double float int long Object String StringBuffer】


以下の例ではappendメソッドで使用した例をそのまま使って文字列の挿入を行っています。

appedメソッドの前に、insertメソッドを使用して、”の読み方”という文字列を挿入してます。

public class Test {
    public static void main(String[ ] args) {

		StringBuilder s=new StringBuilder("名前は");

		//追加
		s.insert(2,"の読み方");

		s.append("サトウです。");

		System.out.println(s);
    }
}

出力結果

名前の読み方はサトウです。

インデックス[2]を指定したので "名前" と "は" の間に "の読み方" が挿入されています。

そのあとにappendメソッドで"サトウです。"が追加されているのがわかると思います。


第一引数に文字数以上のインデックスを指定すると例外が発生します。

public class Test {
    public static void main(String[ ] args) {

		StringBuilder s=new StringBuilder("名前は");

		s.insert(4,"の読み方");

		System.out.println(s);
    }
}
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: offset 4,length 3

注意しましょう。



- deleteメソッド

StringBuilder delete(int beginIndex, int endIndex)

指定されたインデックスの範囲の文字列を削除します。

引数に削除する文字列の開始位置(beginIndex)と終了位置(endIndex)を指定します。

削除の対象となるのは、「beginIndexからendIndex-1」の範囲であることを覚えておきましょう!


deleteメソッドを使用して文字列の削除する例を見てみましょう。

今回は"いいこっか"(いい国家)というString文字列を格納してBuilderオブジェクトを生成しました。


 .い .い .こ .っ .

 ↑   ↑  ↑  ↑  ↑ 

  0  1   2   3   4  


インデックス1~4の範囲の文字列を削除します。

public class Test {
    public static void main(String[ ] args) {

		StringBuilder s=new StringBuilder("いいこっか");

		s.delete(1,4);

		System.out.println(s);
   }
}

出力結果

いか

インデックス1~4の範囲の文字列が削除され、「いか」のみが残りました。


- replaceメソッド

StringBuilder replace(int beginIndex, int endIndex, String str)

このメソッドはインデックスで指定した範囲の文字列を、第三引数で指定した文字列に置き換えます。

第一、第二引数には置き換える文字列の開始位置(beginIndex)と終了位置(endIndex)を指定します。

置き換えの対象となるのは、「beginIndexからendIndex-1」の範囲であることを覚えておきましょう!


deleteメソッドと同じ例を用いて、replaceメソッドで文字列を置き換えましょう。


 .い .い .こ .っ .か     .い  .ぶ  .ん  .か 

  ↑   ↑  ↑  ↑  ↑  ⇔  ↑   ↑   ↑   ↑  

  0  1   2   3   4          0  1   2    3     


インデックス1~4の範囲の文字列を指定した文字列で置き換えます。

public class Test {
    public static void main(String[ ] args) {

		StringBuilder s=new StringBuilder("いいこっか");

		s.replace(1,4,"ぶん");

		System.out.println(s);
    }
}

出力結果

いぶんか

インデックス1~4の範囲 "いこっ" が指定した文字列 "ぶん" に置き換わっています。

Builderクラスのreplaceメソッドでは、第二引数に文字数以上の値を指定しても例外が発生しません。

Stringクラスのreplaceメソッドの場合は例外が発生してしまいます。


Stringクラスの置換/replaceメソッドは以下の記事で紹介しています。

参考:【Java】Stringクラスについての理解と基本的な文字列操作


- reverseメソッド

StringBuilder reverse()

このメソッドは、文字列の順序を逆に置き換えることができます。

引数を指定する必要はありません。


 .い .い .こ .っ .か     .か .っ .こ .い .い

 ↑  ↑  ↑  ↑  ↑  ⇔  ↑  ↑  ↑  ↑  ↑ 

  0   1   2   3   4          0   1   2    3   4 


今回も同様の例を用いて、reverseメソッドで文字列の順序を逆に置き換える例を見てみましょう。

public class Test {
    public static void main(String[ ] args) {
		
        StringBuilder s=new StringBuilder("いいこっか");	
        
        s.reverse();

        System.out.println(s);
    }
}

出力結果

かっこいい


- substirngメソッド

Substirngメソッドは文字列の中から指定した部分の文字列を切り出すことができます。

文字列を切り出す場合はインデックス(文字の位置)を指定する必要があります。


Stringクラスのsubstringメソッドは以下の記事で紹介しています。(インデックスの考え方についても記述してあります。)

参考:【Java】Stringクラスについての理解と基本的な文字列操作


開始位置を指定した切り出し

String substring(int beginIndex)

開始位置を指定する切り出しの場合は引数に開始位置のインデックス(beginIndex)を指定します。


今回は、4番目を開始位置に指定します。


  .い .い .こ .っ .か

 ↑  ↑  ↑  ↑  ↑ 

  0   1   2   3   4  


4番目の.(ピリオド)以降の文字列が切り出されます。

public class Test{
    public static void main(String[] args){

        StringBuilder s=new StringBuilder("いいこっか");

        System.out.println(s);
        System.out.println("切り出し:"+s.substring(4));
   }
}

出力結果

いいこっか
切り出し:か

4番目に開始位置を指定したので、「か」が切り出されました。


範囲を指定した切り出し

String substring(int beginIndex,int endIndex)

範囲を指定する切り出しの場合は

第一引数に開始位置のインデックス(beginIndex)

第二引数に終了位置のインデックス(endIndex)を指定します。


今回は2番目から5番目までの範囲を指定します。


  .い .い .こ .っ .か .

 ↑  ↑  ↑  ↑  ↑  ↑ 

  0   1   2   3   4  5 


範囲を指定するとき際に注意するのはインデックスの範囲の取り方です。


文字ではなく、文字の前にある.(ピリオド)の範囲を取るので覚えておきましょう!

( Builderクラスでは文字数までを範囲にすることができます。)

public class Test{ 
    public static void main(String[] args) {

        StringBuilder s=new StringBuilder("いいこっか");

        System.out.println(s);
        System.out.println("切り出し:"+s.substring(2,5));
    }
}

出力結果

いいこっか

切り出し:こっか

範囲を指定した「こっか」が切り出されました。


- indexOfメソッド

int indexOf(String str)

indexOfメソッドは、

引数に指定された部分文字列(String str)が最初に出現する位置のインデックスをint型で返します。


  .い .い .こ .っ .か .

 ↑  ↑  ↑  ↑  ↑  ↑ 

  0   1   2   3   4  5 


今回は引数を "こっか" にしてindexOfメソッドを使ってみましょう!

public class Test {
    public static void main(String[ ] args) {

        StringBuilder s= new StringBuilder("いいこっか");

        int i=s.indexOf("こっか");

        System.out.println(i);
    }
}

出力結果

2


StringクラスにもindexOfメソッドが用意されています。以下の記事で紹介しています。

参考:【Java】Stringクラスの文字列比較・判定・検索




Stringオブジェクトの生成法

Builder・BufferオブジェクトをStringオブジェクトに変更する操作を紹介します。

- Stringクラスのコンストラクタを利用した方法

String String(StringBuilder builder)
String String(StringBuffer buffer)

引数に指定された、BuilderまたはBufferオブジェクトを使って、新しいStringオブジェクトを生成します。


例をみてみましょう。

public class Test {
    public static void main(String[ ] args) {

        StringBuilder s= new StringBuilder("いいこっか");

        //コンストラクタの生成
        String  str =  new String(s);

        System.out.println(str);
    }
}

出力結果

いいこっか

新しく生成されたStringオブジェクト「str」に、Builderオブジェクト「s」の値が格納されている事が確認できます。


- toStringメソッドを利用した方法

String toString()

Builderクラス、BufferクラスにはtoStringメソッドが用意されています。

Builder・BufferオブジェクトをStringオブジェクトに変換します。


例を見てみましょう。

public class Test {
    public static void main(String[ ] args) {

        StringBuilder s= new StringBuilder("いいこっか");

        String t= s.toString();

        System.out.println(t);
    }
}

出力結果

いいこっか

Bilderオブジェクトが、toStringメソッドによってString変数(t)へ格納ができるようになっています。


【著者】

新人SE・サトウ

読者を始め私自身も知りたい!と思うような知って得するプログラミング知識やIT情報を日々発信中です。
筆者の憧れの人物は、コリン・ファースさん、渡部篤郎さん。
教養のあるカッコいい大人になれるよう、プログラミングを始め興味関心を持ったことを毎日勉強しております !!

よく読まれている記事
【Java】JSPでタグライブラリを使う(JSTL)

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様

【Java】よく使う日時クラス解説まとめ

【Java】よく使う日時クラス解説まとめ

こんにちは、駆け出しエンジニアの伊藤です。東京ITカレッジのJava研修で学んだ内容を復習も兼ねて記事にしたいと思います。今回は、日付時刻のまとめとして、日付時刻に関する基本的なクラスやメソッド等の概要を紹介していきます。より詳しく知りたい!という方は、リンク先の関連記事をご参考にしてください。Javaやプログラムについて勉強し始めた方の参考になれば幸いです!(eclipseを使用して計算を行って