0Pricing
Java Academy · レッスン

効率的な連結のための StringBuilder

ループ内や複雑なフォーマット処理で StringBuilder を使い、効率的に文字列を組み立てます。

「効率的な連結のための StringBuilder」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。

効率的な連結のためのStringBuilder

StringBuilderは、テキストを段階的に構築するための、Stringの可変な代替手段です。多数の中間Stringオブジェクトが生成されるのを防ぎます。

StringBuilderとString連結の比較

多数の文字列を連結する場合(特にループ内では)、StringBuilderの方が大幅に高速です。新しいオブジェクトを生成する代わりに、内部のcharバッファーを変更するためです。

// Inefficient: creates a new String every iteration
String result = "";
for (int i = 0; i < 1000; i++) {
    result += i + ","; // 1000 new String objects!
}

// Efficient: StringBuilder uses a resizable char buffer
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append(i).append(',');
}
String efficient = sb.toString(); // one final String created

StringBuilder API

主なメソッド:append、insert、delete、replace、reverse、toString、length、charAt、setCharAt。

StringBuilder sb = new StringBuilder("Hello");

sb.append(", World");     // Hello, World
sb.insert(5, "!");        // Hello!, World
sb.delete(5, 6);           // Hello, World
sb.replace(7, 12, "Java"); // Hello, Java
sb.reverse();               // avaJ ,olleH
sb.reverse();               // Hello, Java

System.out.println(sb);         // Hello, Java
System.out.println(sb.length()); // 11
System.out.println(sb.charAt(0)); // H

append呼び出しのチェーン

appendなどの変更メソッドはすべてthisを返すため、流れるようにメソッドを連結できます。

StringBuilder html = new StringBuilder()
    .append("<div class=\"card\">")
    .append("<h2>").append("Product Title").append("</h2>")
    .append("<p>Price: $").append(String.format("%.2f", 29.99)).append("</p>")
    .append("<button>Add to Cart</button>")
    .append("</div>");

System.out.println(html.toString());

初期容量

想定される容量を指定してStringBuilderをあらかじめ初期化すると、内部配列のサイズ変更を避けられ、大きな文字列の処理性能が向上します。

// Default capacity: 16 chars
StringBuilder small = new StringBuilder();

// Pre-sized: 10 items * ~50 chars each
StringBuilder report = new StringBuilder(500);

for (int i = 1; i <= 10; i++) {
    report.append(String.format("%-3d. Record %04d: processed OK%n", i, i));
}

System.out.println(report.toString().substring(0, 30));
// "  1. Record 0001: processed OK"

deleteCharAtと特定の削除

deleteCharAtは1文字を削除します。delete(start, end)は範囲を削除します。これらは配列の要素を移動する必要があるため、O(n)です。

StringBuilder sb = new StringBuilder("Hello, World!");

sb.deleteCharAt(5);     // removes comma: "Hello World!"
sb.delete(5, 6);         // removes space: "HelloWorld!"

System.out.println(sb); // HelloWorld!

// Replace to fix a typo
StringBuilder typo = new StringBuilder("Helo, Java!");
typo.replace(typo.indexOf("Helo"), typo.indexOf("Helo") + 4, "Hello");
System.out.println(typo); // Hello, Java!

CSVの構築

実用的なパターンとして、StringBuilderを使ってCSV行を構築し、区切り文字を適切に処理する方法があります。

import java.util.List;

static String toCsv(List<String> values) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < values.size(); i++) {
        if (i > 0) sb.append(',');
        sb.append(escapeCsv(values.get(i)));
    }
    return sb.toString();
}

static String escapeCsv(String s) {
    if (s.contains(",") || s.contains("\""))
        return "\"" + s.replace("\"", "\"\"") + "\"";
    return s;
}

System.out.println(toCsv(List.of("Alice", "Smith, Jr.", "30")));
// Alice,"Smith, Jr.",30

区切り文字で分割された出力のためのStringJoiner

StringJoinerを使うと、区切り文字と、必要に応じて接頭辞および接尾辞を指定して要素を簡単に結合できます。区切り文字を手動で処理する必要はありません。

import java.util.StringJoiner;

StringJoiner sj = new StringJoiner(", ", "[", "]");
sj.add("Alice");
sj.add("Bob");
sj.add("Charlie");
System.out.println(sj.toString()); // [Alice, Bob, Charlie]

// Equivalent with String.join
String joined = String.join(", ", "Alice", "Bob", "Charlie");
System.out.println(joined); // Alice, Bob, Charlie

// Streams: collect with joining collector
import java.util.stream.*;
List.of("a", "b", "c").stream()
    .collect(Collectors.joining(", ", "(", ")"));
// (a, b, c)

StringBuilderとStringBuffer

StringBufferは、スレッドセーフで同期化されたStringBuilderです。ロックのため低速です。単一スレッドのコンテキスト(ケースの99%)ではStringBuilderを使用してください。

// StringBuffer: thread-safe but slower (synchronized methods)
StringBuffer buf = new StringBuffer();
buf.append("Thread-safe");
buf.append(" but slow");

// StringBuilder: not thread-safe but faster
StringBuilder sb = new StringBuilder();
sb.append("Fast");
sb.append(" single-threaded");

// When to use StringBuffer:
// - Multiple threads write to the same buffer
// - Almost always a design smell — redesign to avoid sharing

反転と回文チェック

StringBuilderに組み込まれたreverse()を使うと、回文チェックを簡潔に実装できます。

static boolean isPalindrome(String s) {
    String cleaned = s.toLowerCase()
        .replaceAll("[^a-z0-9]", ""); // remove non-alphanumeric
    String reversed = new StringBuilder(cleaned).reverse().toString();
    return cleaned.equals(reversed);
}

System.out.println(isPalindrome("A man, a plan, a canal: Panama")); // true
System.out.println(isPalindrome("race a car"));                      // false
System.out.println(isPalindrome("Was it a car or a cat I saw?"));    // true

実践:SQLクエリービルダー

条件に応じてwhere句を追加しながら、StringBuilderを使って動的なSQLクエリーを構築します。

static String buildQuery(String category, Double minPrice, Double maxPrice) {
    StringBuilder sql = new StringBuilder("SELECT * FROM products WHERE 1=1");
    if (category != null)
        sql.append(" AND category = '" + category + "'");
    if (minPrice != null)
        sql.append(" AND price >= ").append(minPrice);
    if (maxPrice != null)
        sql.append(" AND price <= ").append(maxPrice);
    sql.append(" ORDER BY name");
    return sql.toString();
}

System.out.println(buildQuery("Electronics", 50.0, null));
// SELECT * FROM products WHERE 1=1 AND category = 'Electronics' AND price >= 50.0 ORDER BY name

確認問題

ループ内で+を使って文字列を連結すると非効率なのはなぜですか。

まとめ:効率的な連結のためのStringBuilder

要点:

  • StringBuilderは可変であり、append/insert/deleteによって内部バッファーを変更します
  • O(n²)の文字列生成を避けるため、ループではStringBuilderを使用します
  • 変更メソッドはすべてthisを返すため、流れるようにメソッドを連結できます
  • 内部のサイズ変更を減らすため、想定される容量でStringBuilderを初期化します
  • StringJoinerとString.joinは、区切り文字で分割された出力に便利です
  • StringBufferは同期化された(スレッドセーフな)代替手段ですが、低速です

よくある質問

「効率的な連結のための StringBuilder」レッスンは無料ですか?

はい。「効率的な連結のための StringBuilder」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。

「効率的な連結のための StringBuilder」で何を学びますか?

ループ内や複雑なフォーマット処理で StringBuilder を使い、効率的に文字列を組み立てます。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Java Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「効率的な連結のための StringBuilder」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このJava Academyレッスンでコードを書いて実行できますか?

はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. String の不変性と String Pool
  2. 効率的な連結のための StringBuilder
  3. テキストブロックと String.format
  4. Pattern と Matcher による正規表現
← Java Academyに戻る