【Java入門 実用編】StringBuilder クラスの利用(2)
2025.09.05
前回の記事では、SrtingBuilder クラスを利用して挿入、削除、反転などの編集を行う方法や、シーケンスから部分的な切り出しなどを行うメソッドについてご紹介しました。当記事では、シーケンスの内容の比較や、文字列の出現位置、シーケンスの長さなどの情報の取得、複数のメソッドを用いた利用例などをご紹介します。
文字列の比較・情報取得
compareTo メソッド(シーケンスの比較)
compareTo メソッドは、2つの StringBuilder のシーケンスを辞書的に比較します。
compareTo メソッド - Java 21 APIドキュメント
2つのシーケンスの内容が同一の場合は 0、メソッド呼び出し側のシーケンスの内容が辞書的に前の場合は負の値、逆の場合は正の値が返されます。StringBuilder クラスの equals メソッドはインスタンスが同一かどうかを返すため、異なる StringBuilder の内容が同一かどうかを確認する場合は、この compareTo メソッドを利用して判定します。
StringBuilder sb1 = new StringBuilder("AAA");
StringBuilder sb2 = new StringBuilder("AAA");
StringBuilder sb3 = new StringBuilder("AAZ");
// シーケンスの内容が同一の場合は「0」を出力
System.out.println(sb1.compareTo(sb2));
/* 異なる場合は、最初に異なった箇所のコードポイントの差を出力 */
// メソッド呼び出し側のシーケンスの内容が辞書的に「前」の場合は負の値
System.out.println(sb1.compareTo(sb3));
// メソッド呼び出し側のシーケンスの内容が辞書的に「後」の場合は正の値
System.out.println(sb3.compareTo(sb1));
ただし、この「辞書的」の比較内容は、コードポイントの大小による比較のため、漢字や濁音などを含む日本語などの言語では想定と異なる並び順となることがあることに注意してください。
StringBuilder sb1 = new StringBuilder("あいうえお");
StringBuilder sb2 = new StringBuilder("アイウエオ");
StringBuilder sb3 = new StringBuilder("安以宇衣於");
StringBuilder sb4 = new StringBuilder("加畿久計己");
// 「あいうえお」は「アイウエオ」より前(負の値)
System.out.println(sb1.compareTo(sb2));
// 「安以宇衣於」は「加畿久計己」より後(正の値)
System.out.println(sb3.compareTo(sb4));
indexOf メソッド(出現位置の取得)
indexOf メソッドは、指定した文字列がシーケンス内に最初に出現する位置を返します。
indexOf メソッド - Java 21 APIドキュメント
引数に指定した文字列が含まれている場合は、最初に出現した位置(インデックス)を、含まれていない場合は -1 を返します。また、第2引数に検索を開始する位置を指定することで、文字列の途中から検索することも可能です。
StringBuilder sb = new StringBuilder("ABCDEABCDEABCDEABCDE");
// 「1」(最初に「BC」が現れる位置)が出力される
System.out.println(sb.indexOf("BC"));
// 「6」(インデックス:2 以降で「BC」が現れる位置)が出力される
System.out.println(sb.indexOf("BC", 2));
// 最後まで出現しない場合は「-1」が出力される
System.out.println(sb.indexOf("XYZ"));
lastIndexOf メソッド(最終出現位置の取得)
lastIndexOf メソッドは、指定した文字列がシーケンス内に最後に出現する位置を返します。
lastIndexOf メソッド - Java 21 APIドキュメント
引数に指定した文字列が含まれている場合は、最後に出現した位置(インデックス)を、含まれていない場合は -1 を返します。また、第2引数に検索を開始する位置を指定することで、文字列の途中から検索することも可能です。この場合、indexOf メソッドとは異なり、指定した位置から先頭に向かって検索する位置が進行することに注意してください。
StringBuilder sb = new StringBuilder("ABCDEABCDEABCDEABCDE");
// 「16」(最後に「BC」が現れる位置)が出力される
System.out.println(sb.lastIndexOf("BC"));
// 「11」(インデックス:12 よりも前で最後に「BC」が現れる位置)が出力される
System.out.println(sb.lastIndexOf("BCDE", 12));
// 最後まで出現しない場合は「-1」が出力される
System.out.println(sb.lastIndexOf("XYZ"));
第二引数に検索を開始する位置を指定した場合、検索対象とする文字列が指定した位置以前から始まっていれば、検索文字列が全てその位置よりも前になくても良いことに注意してください。上記のサンプルコードでは、文字列「ABCDEABCDEABCDEABCDE」に対して、検索文字列に「BCDE」、検索開始位置に「12」と指定した際に、インデックスが 11~14 の位置にある「BCDE」(ABCDEABCDEABCDEABCDE)がヒットします。
シーケンスの長さ、容量の取得・最適化
length メソッド(シーケンス長の取得)
length メソッドはシーケンスの現在の長さ(文字数)を返します。
lengthメソッド - Java 21 APIドキュメント
length メソッドではアルファベットや数字、かな、漢字などの字種を問わず、シーケンス内の文字数が返されます。
// デフォルトのインスタンス(空のシーケンス)
StringBuilder sb = new StringBuilder();
// 長さを確認 - 「0」が出力される
System.out.println(sb.length());
// アルファベット、数字を追加
sb.append("abc").append(123);
// 長さを確認 - 「6」が出力される
System.out.println(sb.length());
// 日本語(ひらがな、全角/半角カナ、漢字)を追加
sb.append("あ").append("ア").append("ア").append("亜");
// 長さを確認 - 「10」が出力される
System.out.println(sb.length());
capacity メソッド(容量の取得)
capacity メソッドは、StringBuilder の現在の容量を返します。
capacity メソッド - Java 21 APIドキュメント
// デフォルトの初期容量は16
StringBuilder sb = new StringBuilder();
// 容量を確認 - 「16」が出力される
System.out.println(sb.capacity());
// 容量を指定してインスタンスを生成
sb = new StringBuilder(100);
// 容量を確認 - 「100」が出力される
System.out.println(sb.capacity());
前回の記事でご紹介した通り、StringBuilder クラスでは append メソッドや insert メソッドで文字列を連結して、容量が足りなくなった場合は自動的に容量が拡張されます。
ensureCapacity メソッド(容量の拡張)
ensureCapacity メソッドは、StringBuilder の容量を、引数で指定したサイズ以上となるように必要に応じて拡張します。
ensureCapacity メソッド - Java 21 APIドキュメント
現在の容量が指定したサイズ以上である場合は、このメソッドでは何も行われません。容量が指定したサイズよりも小さい場合は、「指定したサイズ」または「(現在の容量 × 2)+ 2」のいずれか大きいほうの容量に拡張されます。
// 初期の容量は24(8 + 16)
StringBuilder sb = new StringBuilder("ABCDEFGH");
// 容量を確認 - 「24」が出力される
System.out.println(sb.capacity());
// 1. 容量に「32」を指定 - 32 と 50(24 * 2 + 2)の大きい方が適用される
sb.ensureCapacity(32);
// 容量を確認 - 「50」が出力される
System.out.println(sb.capacity());
// 2. 容量に「150」を指定 - 150 と 102(50 * 2 + 2)の大きい方が適用される
sb.ensureCapacity(150);
// 容量を確認 - 「150」が出力される
System.out.println(sb.capacity());
// 3. 容量に現在の容量以下の値(100)を指定
sb.ensureCapacity(100);
// 容量を確認 - 「150」が出力される(容量は変更されていない)
System.out.println(sb.capacity());
trimToSize メソッド(容量の最適化)
trimToSize メソッドは、StringBuilder の容量を、現在の文字数に応じたサイズに最適化(低減)します。
trimToSize メソッド - Java 21 APIドキュメント
trimToSize メソッドでは、StringBuilder の現在の容量がシーケンスの文字を格納するために必要なサイズよりも大きい場合、最低限の容量となるように試みます。
// 初期の容量は24(8 + 16)
StringBuilder sb = new StringBuilder("ABCDEFGH");
// 容量を確認 - 「24」が出力される
System.out.println(sb.capacity());
// 容量の最適化
sb.trimToSize();
// 再度容量を確認 - 「8」が出力される
System.out.println(sb.capacity());
StringBuilder クラスのメソッド利用例
特定の文字列が含まれているかどうかの判定
StringBuilder クラスでは String クラスの contains メソッドに対応するメソッドは準備されていないため、特定の文字列が含まれているかどうかの判定を行いたい場合は indexOf メソッドを利用してはんていすることができます。
StringBuilder sb = new StringBuilder("vwxyz");
// 文字列「xyz」が含まれている場合のみ処理を行う
if( sb.indexOf("xyz") > -1 ) {
System.out.println("文字列「xyz」が含まれています。");
}
シーケンス内の特定の文字列を全て除去、置換する
StringBuilder クラスでは、String クラスの replace メソッドのように、シーケンス内の特定の文字(列)をまとめて除去したり、置換するメソッドは実装されていません。
削除や置換した内容で StringBuilder のインスタンスを引き続き利用したい場合、一旦 toString メソッドで String として処理してから再度 StringBuilder のインスタンスを生成することだと思いますが、 indexOf メソッドと delete メソッドや replace メソッドを組み合わせることで、使用中の StringBuilder インスタンスに対して直接特定の文字列を全て除去したり、全て置換するといった処理を行うこともできます。
// 特定の文字列が見つからなくなるまで、その範囲を削除する例
StringBuilder sb = new StringBuilder("abcdefabcdefabcdef");
String target = "abc";
int idx = sb.indexOf(target);
int len = target.length;
// 見つからなくなるまで繰り返し削除
while( idx > -1 ) {
sb.delete( idx, len );
idx = sb.indexOf(target);
}
固定長の文字列を作成する
length メソッドと repeat メソッドを利用することで、繰り返し処理を記述せずに固定長の文字列を作成することができます。
StringBuilder sb = new StringBuilder();
// 0 ~ 999 のいずれかを追加
sb.append( (int)( Math.random() * 1000) );
// 3桁に満たない場合は3桁になるまで後方に半角スペースを追加
sb.repeat(" ", 3 - sb.length());
また、以下の例では数値(0 ~ 999)を前方を半角スペース埋めとした3桁の固定長として、10個を並べて30桁の固定長の文字列を作成しています。repeat メソッドを利用することで、if 文やループ処理を記述せずに桁数が不足する時だけ半角スペースを追加することで、最小限の階層でコーディングできます。
// 実行結果を格納するStringBuilder
StringBuilder result = new StringBuilder();
// 実行結果に追加するタイミングで達するべき桁数
int count = 0;
for(int i = 0; i < 10; i++) {
// 今回のループで達するべき桁数
count += 3;
// 一時的に乱数の結果を文字列に格納
String tmp = "" + (int)(Math.random() * 1000);
// 足りない桁の分を先にスペースで埋めてから、乱数の結果を格納
result.repeat(" ", count - (result.length() + tmp.length()))
.append(tmp);
}