Java String Concatenation
Join strings in Java using the + operator, concat(), and StringBuilder, and compare their performance.
"Concatenation" just means joining strings end to end. Java gives you several ways to do it — +, concat, String.format, text blocks, StringBuilder, String.join. They differ in readability and, when looped, in performance.
The + operator
+ is the everyday way:
String first = "Ada";
String last = "Lovelace";
String full = first + " " + last; // "Ada Lovelace"It also converts non-strings to strings via their toString():
int age = 36;
String s = "Age: " + age; // "Age: 36"Behind the scenes the compiler turns a + b + c into a single StringBuilder.append(...).append(...).toString(). So one chained + expression is efficient.
concat
String.concat(other) returns this string followed by other:
"Hello, ".concat("World!"); // "Hello, World!"It's effectively the same as +, but only accepts a String (no autoconversion). Most code just uses +.
String.format and formatted
For multi-piece concatenation with type-specific formatting, String.format is cleaner than long chains of +:
String name = "Ada";
int age = 36;
String s = String.format("%s is %d years old", name, age);Since Java 15, the instance method formatted is equivalent and reads left-to-right:
"%s is %d years old".formatted(name, age);Text blocks for multi-line
For multi-line strings, the text-block syntax (Java 15+) avoids long \n chains:
String json = """
{
"name": "%s",
"age": %d
}
""".formatted(name, age);StringBuilder — for loops
Each + on a String creates a new object. In a loop with thousands of iterations, that's a lot of garbage. Use StringBuilder instead — it has a mutable internal buffer:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("line ").append(i).append("\n");
}
String result = sb.toString();The StringBuilder methods you'll use:
append(any)— add to the end (returns the builder so you can chain).insert(index, any)— insert at a position.delete(start, end)— remove a range.reverse()— reverse the builder's contents.length()andsetLength(n)— read / truncate.toString()— produce the finalString.
There's also StringBuffer, which is identical but thread-safe (every method is synchronized). You almost never need it — use StringBuilder unless you genuinely share the builder between threads.
String.join — for collections
When you have a collection of strings and a separator, String.join is the cleanest:
String csv = String.join(",", "a", "b", "c"); // "a,b,c"
String csv2 = String.join(", ", List.of("a", "b", "c")); // "a, b, c"For more advanced joining (collectors, conditional inclusion), see streams' Collectors.joining later in the book.
When to use which
A rough decision tree:
- One or two pieces, readable left-to-right →
+. - Several pieces with type formatting →
String.formatorformatted. - Multi-line literal → text block, optionally with
.formatted. - Building piece by piece in a loop →
StringBuilder. - Joining a collection with a separator →
String.join.
For small concatenations, modern compilers and the JVM (with the invokedynamic-based string concat introduced in Java 9) make + very fast — performance is not a reason to avoid it for simple cases.
A demonstration of the loop case
What's next
Java Special Characters and Escape Sequences — what \n, \t, \", and the Unicode escapes do.
Practice
Which approach is best for building a long string inside a 10,000-iteration loop?