文字列結合の全体像
Javaの文字列結合は「複数の値をひとつの文字列にまとめる」操作です。もっとも基本は + 演算子ですが、用途によって StringBuilder、String.join、String#concat、String#format(System.out.printf)などを使い分けます。重要なのは「文字列の不変性(immutable)」を理解し、処理量に応じて適切な手段を選ぶことです。
+ 演算子での結合(最小・直感・注意点)
基本的な使い方
String s = "Hello" + " " + "World";
System.out.println(s); // Hello World
Java短い結合や可読性が最優先の場面では + が最も自然です。数値や他型が混在するときは自動で文字列化されます。
int n = 42;
String msg = "n=" + n; // "n=42"
Java順序と型変換の落とし穴
System.out.println(1 + 2 + "A"); // "3A"
System.out.println("A" + 1 + 2); // "A12"
Java左から順に評価されるため、数値計算を先にしたいのか、文字列化を先にしたいのかで結果が変わります。意図が曖昧なら括弧で明示します。
System.out.println("A" + (1 + 2)); // "A3"
Java連続結合は StringBuilder(性能重視の基本形)
不変性とコストの理解
String は不変であり、+ を使うたびに新しい文字列が生成されます。ループでの連続結合はオブジェクトが大量に増えるため、StringBuilder で可変バッファへ「追記」するのが定石です。
String[] parts = {"Java", "is", "fast"};
StringBuilder sb = new StringBuilder();
for (String p : parts) {
if (sb.length() > 0) sb.append(' ');
sb.append(p);
}
String s = sb.toString();
System.out.println(s); // "Java is fast"
JavaStringBuilder は単一スレッド向け、複数スレッドで共有するなら同期版の StringBuffer を検討します(通常は共有しない設計が安全です)。
用途別の標準API(意図が伝わる選択)
区切りで連結したいなら String.join
String s = String.join(", ", "A", "B", "C");
System.out.println(s); // "A, B, C"
Java配列やリストなら次のように書けます。
java.util.List<String> list = java.util.List.of("Tokyo", "Osaka", "Nagoya");
String cities = String.join(" / ", list);
Javaフォーマットで整えたいなら String.format
String label = String.format("price=%,d tax=%.1f%%", 12345, 10.0);
System.out.println(label); // "price=12,345 tax=10.0%"
Java整列や小数点桁数、桁区切りを同時に扱う場合、format(または printf)が最短ルートです。
ほんの少しの結合なら concat
String s = "Hello".concat(" ").concat("World");
Javaconcat は null を受けると例外になる点に注意が必要です。+ は null を「”null”」として連結します(好ましくない場合があるため、null の扱いを設計で決めておきましょう)。
null とトリミング、文字列化の安全策(重要ポイントの深掘り)
null の安全な文字列化
String name = null;
String safe = String.valueOf(name); // "null"
Java見せたくない場合は既定値で置き換えます。
String safeName = (name != null) ? name : "";
Java前後空白や空文字の扱い
String raw = " Java ";
String s = raw.trim() + "!";
System.out.println(s); // "Java!"
Java入力を連結する前に trim() で整えると、意図しない空白の混入を防げます。空文字は「意味のある欠損表現か」を決めて統一しましょう。
大量データ・ループ・国際化での設計(重要ポイントの深掘り)
ループでの組み立て
たくさんの要素の結合は StringBuilder または String.join を選びます。数千〜数万回の + は避けると、メモリとCPUの無駄を減らせます。
StringBuilder sb = new StringBuilder(1024); // 事前容量でリサイズ回数を減らす
Javaロケールや数字書式が絡む文字列
ユーザー向けの文字列は「表示の整形」と「結合」を分離すると誤差や表記揺れを回避できます。数値は String.format(Locale, ...)、日時は DateTimeFormatter、通貨は NumberFormat.getCurrencyInstance(locale) を使い、結合は最後に行うのが安全です。
例題で身につける
例 1: 区切り文字を最後だけ出さない(StringBuilder)
public class JoinSafe {
public static void main(String[] args) {
String[] a = {"Java", "is", "fun"};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < a.length; i++) {
sb.append(a[i]);
if (i != a.length - 1) sb.append(", ");
}
System.out.println(sb.toString()); // "Java, is, fun"
}
}
Java例 2: 行を受けてから安全に連結(null と空白対策)
public class SafeConcat {
static String safe(String s) { return (s == null) ? "" : s.trim(); }
public static void main(String[] args) {
String first = safe(" Sato ");
String last = safe(null);
String full = first + " " + last; // 最後の空白は後でtrim
System.out.println(full.trim()); // "Sato"
}
}
Java例 3: 書式と結合の分離(読みやすさと再利用性)
public class FormatAndConcat {
public static void main(String[] args) {
String price = String.format(java.util.Locale.JAPAN, "%,d円", 1234567);
String tax = String.format("%.1f%%", 10.0);
String msg = String.join(" / ", price, "tax=" + tax);
System.out.println(msg); // "1,234,567円 / tax=10.0%"
}
}
Java仕上げのアドバイス(重要部分のまとめ)
文字列は不変であり、連続結合は StringBuilder が定石。短い結合や読みやすさ重視は +、区切り連結は String.join、整形は String.format を使い分ける。null の扱いとトリミングを事前に決め、順序評価の落とし穴(数値→文字列化)を括弧で回避する。大量結合は事前容量の StringBuilder で効率化し、国際化や表示整形は専用APIに任せてから結合する。この癖が、バグを減らしつつパフォーマンスと可読性を両立させます。
