Java String Concatenation Explained: Best Methods, Performance, and Best Practices

目次

1. Introduction

Want to concatenate strings in Java? This is a topic that everyone encounters at least once, from programming beginners to professional developers. Common scenarios include combining multiple names into a single sentence, building SQL statements for databases, or outputting clear and readable log messages. String concatenation is indispensable in many use cases.

However, many developers struggle with questions such as “Which method is the best?”, “What is the difference between the + operator and StringBuilder?”, or performance issues like “My program suddenly became slow after concatenating a large amount of data.”

In this article, we provide a comprehensive and beginner-friendly explanation of all major string concatenation methods in Java. From simple concatenation techniques to performance considerations, memory efficiency, and recommended patterns in modern Java versions, we cover everything in detail. We also summarize practical best practices and clear decision criteria for choosing the right approach in real-world development.

If you want to master string concatenation in Java or reassess whether your current approach is optimal, read on until the end. You will find knowledge that can be applied immediately in your development work.

2. Basics of String Concatenation in Java

String concatenation appears very frequently in Java programming, yet surprisingly few developers fully understand how it works internally. Let’s start by reviewing the fundamentals of Java strings and the key points you should know when concatenating them.

2.1 Strings Are Immutable Objects

The String type in Java is immutable. This means that once a string object is created, its content cannot be changed.

For example, consider the following code:

String a = "Hello";
a = a + " World!";

Although the variable a ends up containing “Hello World!”, internally a new string object is created. The original “Hello” string is not modified.

While this immutability improves safety and helps prevent bugs, it can negatively impact memory efficiency and performance when a large number of concatenations are performed.

2.2 Why Does Frequent String Concatenation Become Slow?

When you repeatedly concatenate strings using the + operator, a new string object is created each time, and the old one becomes unused.

Consider the following loop:

String result = "";
for (int i = 0; i < 1000; i++) {
    result = result + i;
}

In this case, a new string is created on every iteration, resulting in increased memory consumption and degraded performance.

This phenomenon is often referred to as a “string concatenation pitfall” and is especially important to consider in performance-sensitive applications.

2.3 Understanding the Basic Concatenation Methods

There are two primary ways to concatenate strings in Java:

  • The + operator (e.g., a + b)
  • The concat() method (e.g., a.concat(b))

Both are easy to use, but understanding their usage patterns and internal behavior is the first step toward writing efficient Java code.

3. Comparison of Concatenation Methods and How to Choose Them

Java provides multiple ways to concatenate strings, including the + operator, the concat() method, StringBuilder/StringBuffer, String.join() and StringJoiner, and String.format(). Depending on your Java version and use case, the optimal choice varies. This section explains the characteristics, suitable scenarios, and caveats of each approach.

3.1 Using the + Operator

The most intuitive and straightforward method is using the + operator:

String firstName = "Taro";
String lastName = "Yamada";
String fullName = firstName + " " + lastName;

In Java 8 and later, concatenation using the + operator is internally optimized using StringBuilder. However, repeated concatenation inside loops still requires caution from a performance perspective.

3.2 The String.concat() Method

The concat() method is another basic approach:

String a = "Hello, ";
String b = "World!";
String result = a.concat(b);

Although simple, this method throws an exception if null is passed, which is why it is less commonly used in real-world applications.

3.3 Using StringBuilder and StringBuffer

If performance is a priority, you should use StringBuilder (or StringBuffer when thread safety is required). This is especially important when concatenation occurs multiple times inside a loop.

StringBuilder sb = new StringBuilder();
sb.append("Java");
sb.append("String");
sb.append("Concatenation");
String result = sb.toString();

3.4 String.join() and StringJoiner (Java 8 and later)

When you want to concatenate multiple elements with a delimiter, String.join() and StringJoiner are very convenient options introduced in Java 8.

List<String> words = Arrays.asList("Java", "String", "Concatenation");
String joined = String.join(",", words);

3.5 String.format() and Other Methods

When you need formatted output, String.format() is a powerful option.

String name = "Sato";
int age = 25;
String result = String.format("Name: %s, Age: %d", name, age);

3.6 Comparison Table (Use Cases and Characteristics)

MethodSpeedReadabilityLoop FriendlyJava VersionNotes
+ operator△–○×AllSimple but not recommended in loops
concat()×AllBe careful with null values
StringBuilderAllFastest for loops and large volumes
StringBufferAllRecommended for multithreaded environments
String.join()Java 8+Ideal for arrays and collections
String.format()×AllBest for complex formatting and readability

3.7 Visual Guide for Choosing a Method

  • Short, temporary concatenation: + operator
  • Loops or large volumes of data: StringBuilder
  • Collections or arrays: String.join()
  • Multithreaded environments: StringBuffer
  • Formatted output: String.format()

4. Best Practices by Use Case

Java offers many ways to concatenate strings, but knowing which method to use in which situation is key to improving productivity and avoiding issues in real-world development. This section explains the optimal approach for common scenarios.

4.1 Use the + Operator for Short, Temporary Concatenation

If you are concatenating strings only once or a few times, the + operator is sufficient.

String city = "Osaka";
String weather = "Sunny";
String message = city + " weather is " + weather + ".";
System.out.println(message);

4.2 Use StringBuilder for Loops and Large Concatenations

Whenever concatenation occurs repeatedly or dozens of times or more, StringBuilder should always be used.

StringBuilder sb = new StringBuilder();
for (String word : words) {
    sb.append(word);
}
String output = sb.toString();
System.out.println(output);

4.3 Use String.join() or StringJoiner for Collections and Arrays

When you need to concatenate all elements in an array or list with a delimiter, String.join() or StringJoiner is ideal.

List<String> fruits = Arrays.asList("Apple", "Banana", "Grape");
String csv = String.join(",", fruits);
System.out.println(csv);

4.4 Use StringBuffer in Multithreaded Environments

In concurrent or multithreaded environments, using StringBuffer instead of StringBuilder ensures thread safety.

StringBuffer sb = new StringBuffer();
sb.append("Safe");
sb.append(" and ");
sb.append("Sound");
System.out.println(sb.toString());

4.5 Handling null Values and Special Cases

If null values may be included, String.join() will throw an exception. To concatenate safely, remove or convert null values beforehand.

List<String> data = Arrays.asList("A", null, "C");
String safeJoin = data.stream()
    .filter(Objects::nonNull)
    .collect(Collectors.joining(","));
System.out.println(safeJoin);

4.6 Use String.format() for Formatting and Complex Output

When you need to combine multiple variables into a well-formatted and readable string, String.format() is very useful.

String name = "Tanaka";
int age = 32;
String message = String.format("Name: %s Age: %d", name, age);
System.out.println(message);

Summary

  • Short, temporary concatenation → + operator
  • Loops or large-scale concatenation → StringBuilder
  • Delimited concatenation for collections → String.join() or StringJoiner
  • Concurrent or thread-safe environments → StringBuffer
  • Null handling or formatted output → preprocessing or String.format()

5. Practical Code Examples for Common Patterns

This section introduces commonly used string concatenation patterns in Java with concrete code examples. These examples are ready to use in real projects or learning scenarios.

5.1 Simple Concatenation Using the + Operator

String city = "Osaka";
String weather = "Sunny";
String message = city + " weather is " + weather + ".";
System.out.println(message);

5.2 Using the concat() Method

String a = "Java";
String b = "Language";
String result = a.concat(b);
System.out.println(result);

5.3 Loop-Based Concatenation with StringBuilder

StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 5; i++) {
    sb.append("No.").append(i).append(" ");
}
String output = sb.toString();
System.out.println(output);

5.4 Thread-Safe Concatenation with StringBuffer

StringBuffer sb = new StringBuffer();
sb.append("Safe");
sb.append(" and ");
sb.append("Sound");
System.out.println(sb.toString());

5.5 Concatenating Arrays or Lists with String.join()

List<String> fruits = Arrays.asList("Apple", "Banana", "Grape");
String csv = String.join(",", fruits);
System.out.println(csv);

5.6 Flexible Concatenation with StringJoiner

StringJoiner joiner = new StringJoiner(", ", "[", "]");
joiner.add("A").add("B").add("C");
System.out.println(joiner.toString());

5.7 Advanced Usage with Stream API and Collectors.joining()

List<String> data = Arrays.asList("one", null, "three");
String result = data.stream()
    .filter(Objects::nonNull)
    .collect(Collectors.joining("/"));
System.out.println(result);

5.8 Formatting and Concatenation with String.format()

String user = "Sato";
int age = 29;
String info = String.format("Name: %s, Age: %d", user, age);
System.out.println(info);

5.9 Converting Arrays to Strings (Example with Arrays.toString())

int[] scores = {70, 80, 90};
System.out.println(Arrays.toString(scores));

Summary

Choosing the most appropriate method based on your use case significantly improves the efficiency and quality of Java development.

6. Differences by Java Version and Modern Trends

Java has evolved over many years, and recommended approaches to string concatenation have changed accordingly. This section explains the major differences by Java version and highlights modern development trends.

6.1 Conventional Wisdom up to Java 7

  • Using the + operator was considered simple but inefficient in loops.
  • Repeated concatenation inside loops was strongly discouraged in favor of StringBuilder.
  • Before Java 7, using + generated many intermediate String instances, causing significant performance degradation.

6.2 Optimizations in Java 8 and Later

  • From Java 8 onward, string concatenation using the + operator is internally optimized and translated into StringBuilder operations at compile time or runtime.
  • Even so, using + inside loops is still not considered best practice; StringBuilder or String.join() remains recommended for repeated concatenation.
  • Java 8 introduced String.join() and StringJoiner, making collection-based concatenation much easier.

6.3 Changes and New Features in Java 11 / 17 and Later

  • In LTS (Long-Term Support) versions such as Java 11 and Java 17, the string concatenation APIs themselves have not changed significantly, but JVM-level optimizations have continued to improve, making the + operator even more efficient.
  • In addition, new methods such as String.repeat() and enhanced Stream APIs have expanded the range of string creation and concatenation patterns.

6.4 An Era Where “Old Common Sense” No Longer Applies

  • As Java evolves, techniques that were once considered strictly forbidden are now acceptable in some cases.
  • For example, a few concatenations using the + operator or simple usage within conditional statements rarely cause issues in modern JVMs.
  • However, large-scale concatenation or using + inside loops still carries performance risks, so StringBuilder remains the recommended choice in practice.

6.5 The Latest Trend: Balancing Readability and Performance

  • In many modern development environments, code readability and maintainability are often prioritized over excessive micro-optimizations.
  • A common guideline is: use the + operator for readability, and switch to StringBuilder or String.join() when performance or complexity matters.
  • Declarative styles using the Stream API and Collectors.joining() are also increasingly popular in contemporary Java codebases.

Summary

The optimal approach to string concatenation in Java may vary depending on the version you are using. Avoid relying on outdated advice, and always choose best practices that align with modern Java environments.

7. Frequently Asked Questions (FAQ)

Many developers encounter similar questions and pitfalls when working with string concatenation in Java. This section provides concise answers to the most common ones.

Q1. Why does using the + operator inside loops slow down performance?

While the + operator is simple and intuitive, using it inside loops creates a new string instance on each iteration. For example, concatenating strings 1,000 times in a loop results in 1,000 new string objects, increasing GC pressure and reducing performance. StringBuilder is the standard solution for loop-based concatenation.

Q2. What is the difference between StringBuilder and StringBuffer?

Both are mutable string buffers, but StringBuilder is not thread-safe, while StringBuffer is thread-safe. For single-threaded processing, StringBuilder is faster and recommended. Use StringBuffer only when thread safety is required.

Q3. Can String.join() be used with lists that contain null values?

No. If a list passed to String.join() contains null, a NullPointerException will be thrown. To use it safely, remove null values beforehand or use the Stream API with filter(Objects::nonNull).

Q4. Does String.format() cause performance issues?

String.format() offers excellent readability and formatting flexibility, but it is slower than simple concatenation methods. Avoid using it excessively in performance-critical code paths; instead, prefer StringBuilder or String.join() when speed is crucial.

Q5. Are English-language resources and Stack Overflow answers reliable?

Yes. English-language resources often provide the latest benchmarks and insights into JDK internals. However, always verify the Java version and publication date, as older answers may no longer reflect current best practices.

Q6. How can I avoid errors when concatenating null values?

Methods such as concat() and String.join() throw exceptions when encountering null. The + operator converts null to the string “null”. In practice, it is safer to guard against null using Objects.toString(value, "") or Optional.ofNullable(value).orElse("").

Q7. What are the key checkpoints for maximizing performance?

  • Use StringBuilder for loops and large-scale concatenation
  • Use String.join() or Collectors.joining() for arrays and collections
  • Prioritize simple and correct code first, then optimize based on benchmarks
  • Stay informed about JVM and JDK updates

8. Summary and Recommended Decision Flowchart

This article has covered Java string concatenation from fundamentals to advanced usage, including performance considerations and version-specific differences. Below is a concise summary and a practical decision guide.

8.1 Key Takeaways

  • + operator
    Ideal for small, temporary concatenations and readable code. Not suitable for loops or large-scale processing.
  • StringBuilder
    Essential for repeated or large-scale concatenation. The de facto standard in real-world development.
  • StringBuffer
    Use only when thread safety is required.
  • String.join() / StringJoiner
    Excellent for concatenating arrays, lists, and collections with delimiters. A modern Java 8+ solution.
  • String.format()
    Best for formatted and human-readable output.
  • Stream API / Collectors.joining()
    Useful for advanced scenarios such as conditional concatenation and null filtering.

8.2 Use-Case-Based Method Selection Flowchart

If you are unsure which approach to choose, follow this guide:

1. Large-scale concatenation in loops → StringBuilder
2. Concatenating arrays or lists → String.join() / Collectors.joining()
3. Thread safety required → StringBuffer
4. Small, temporary concatenation → +
5. Formatting required → String.format()
6. Null handling or conditional logic → Stream API + filter + Collectors.joining()
7. Other or special cases → Choose flexibly based on requirements

8.3 Practical Tips When in Doubt

  • If everything works, prioritize readability first.
  • Consult benchmarks and official documentation only when performance or safety becomes a concern.
  • Always verify recommendations against your current JDK version.

8.4 How to Keep Up with Future Java Updates

  • Oracle official documentation and Java Magazine
  • Latest articles on Stack Overflow and Qiita
  • Java Enhancement Proposal (JEP) listings

Conclusion

There is no single “correct” way to concatenate strings in Java—the optimal choice depends on your use case, Java version, and project scale. Being able to select the right method for the situation is a key skill for Java developers. Apply the knowledge from this article to write more efficient, maintainable, and reliable Java code.

9. References and External Resources

To deepen your understanding and stay up to date, consult reliable documentation and well-known technical resources.

9.1 Official Documentation

9.2 Technical Articles and Practical Guides

9.3 Recommended Resources for Further Learning

9.4 Notes and Advice

  • Always check publication dates and Java versions when reading articles.
  • Balance official documentation with community discussions to distinguish current best practices from outdated ones.