Concatenating Strings In Java

1. Introduction

Java provides a substantial number of methods and classes dedicated to concatenating Strings.

In this tutorial, we’ll dive into several of them as well as outline some common pitfalls and bad practices.

2. StringBuilder

First up is the humble StringBuilder. This class provides an array of String-building utilities that makes easy work of String manipulation.

Let’s build a quick example of String concatenation using the StringBuilder class:

StringBuilder stringBuilder = new StringBuilder(100);

stringBuilder.append("Baeldung");
stringBuilder.append(" is");
stringBuilder.append(" awesome");

assertEquals("Baeldung is awesome", stringBuilder.toString());

Internally, StringBuilder maintains a mutable array of characters. In our code sample, we’ve declared this to have an initial size of 100 through the StringBuilder constructor. Because of this size declaration, the StringBuilder can be a very efficient way to concatenate Strings.

It’s also worth noting that the StringBuffer class is the synchronized version of StringBuilder

Although synchronization is often synonymous with thread safety, it’s not recommended for use in multithreaded applications due to StringBuffer’s builder pattern. While individual calls to a synchronized method are thread safe, multiple calls are not.

3. Addition Operator

Next up is the addition operator (+). This is the same operator that results in the addition of numbers and is overloaded to concatenate when applied to Strings.

Let’s take a quick look at how this works:

String myString = "The " + "quick " + "brown " + "fox...";

assertEquals("The quick brown fox...", myString);

At first glance, this may seem much more concise than the StringBuilder option. However, when the source code compiles, the + symbol translates to chains of StringBuilder.append() calls. Due to this, mixing the StringBuilder and + method of concatenation is considered bad practice.

Additionally, String concatenation using the + operator within a loop should be avoided. Since the String object is immutable, each call for concatenation will result in a new String object being created.

4. String Methods

The String class itself provides a whole host of methods for concatenating Strings.

4.1. String.concat

Unsurprisingly, the String.concat method is our first port of call when attempting to concatenate String objects. This method returns a String object, so chaining together the method is a useful feature.

String myString = "Both".concat(" fickle")
  .concat(" dwarves")
  .concat(" jinx")
  .concat(" my")
  .concat(" pig")
  .concat(" quiz");

assertEquals("Both fickle dwarves jinx my pig quiz", myString);

In this example, our chain is started with a String literal, the concat method then allows us to chain the calls to append further Strings.

4.2. String.format

Next up is the String.format method, which allows us to inject a variety of Java Objects into a String template.

The String.format method signature takes a single String denoting our template. This template contains ‘%’ characters to represent where the various Objectsshould be placed within it.

Once our template is declared, it then takes a varargs Object array which is injected into the template.

Let’s see how this works with a quick example:

String myString = String.format("%s %s %.2f %s %s, %s...", "I",
  "ate",
  2.5056302,
  "blueberry",
  "pies",
  "oops");

assertEquals("I ate 2.51 blueberry pies, oops...", myString);

As we can see above, the method has injected our Strings into the correct format.

4.3. String.join (Java 8+)

If our application is running on Java 8 or above, we can take advantage of the String.join method. With this, we can join an array of Strings with a common delimiter, ensuring no spaces are missed.

String[] strings = {"I'm", "running", "out", "of", "pangrams!"};

String myString = String.join(" ", strings);

assertEquals("I'm running out of pangrams!", myString);

A huge advantage of this method is not having to worry about the delimiter between our strings.

5. StringJoiner (Java 8+)

StringJoiner abstracts all of the String.join functionality into a simple to use class. The constructor takes a delimiter, with an optional prefix and suffix. We can append Strings using the well-named add method.

StringJoiner fruitJoiner = new StringJoiner(", ");

fruitJoiner.add("Apples");
fruitJoiner.add("Oranges");
fruitJoiner.add("Bananas");

assertEquals("Apples, Oranges, Bananas", fruitJoiner.toString());

By using this class, instead of the String.join method, we can append Strings as the program runs; There’s no need to create the array first!

Head over to our article on StringJoiner for more information and examples.

6. Arrays.toString

On the topic of arrays, the Array class also contains a handy toString method which nicely formats an array of objects. The Arrays.toString method also calls the toString method of any enclosed object – so we need to ensure we have one defined.

String[] myFavouriteLanguages = {"Java", "JavaScript", "Python"};

String toString = Arrays.toString(myFavouriteLanguages);

assertEquals("[Java, JavaScript, Python]", toString);

Unfortunately, the Arrays.toString method is not customizable and only outputs a String encased in square brackets.

7. Collectors.joining (Java 8+)

Finally, let’s take a look at the Collectors.joining method which allows us to funnel the output of a Stream into a single String.

List<String> awesomeAnimals = Arrays.asList("Shark", "Panda", "Armadillo");

String animalString = awesomeAnimals.stream().collect(Collectors.joining(", "));

assertEquals("Shark, Panda, Armadillo", animalString);

Using streams unlocks all of the functionality associated with the Java 8 Stream API, such as filtering, mapping, iterating and more.

8. Wrap Up

In this article, we’ve taken a deep dive into the multitude of classes and methods used to concatenate Stringsin the Java language.

As always, the source code is available over on GitHub.

Related posts:

Java Program to Find the Shortest Path Between Two Vertices Using Dijkstra’s Algorithm
Java Program to Create a Minimal Set of All Edges Whose Addition will Convert it to a Strongly Conne...
Java Program to Implement Ford–Fulkerson Algorithm
Làm thế nào tạo instance của một class mà không gọi từ khóa new?
Giới thiệu java.io.tmpdir
Spring Boot - Apache Kafka
Java Program to Implement Slicker Algorithm that avoids Triangulation to Find Area of a Polygon
Hướng dẫn sử dụng Java Annotation
String Operations with Java Streams
Java Program to Implement HashSet API
Encode/Decode to/from Base64
Java Program to Implement Bit Array
A Quick Guide to Using Keycloak with Spring Boot
Hướng dẫn Java Design Pattern – DAO
Java Program to Create the Prufer Code for a Tree
Command-Line Arguments in Java
Loại bỏ các phần tử trùng trong một ArrayList như thế nào trong Java 8?
Quick Guide to java.lang.System
Java Program to Implement LinkedList API
Summing Numbers with Java Streams
Hướng dẫn Java Design Pattern – Iterator
Java Program to Solve the Fractional Knapsack Problem
Extract network card address
Java Program to Generate Random Partition out of a Given Set of Numbers or Characters
Java Program to Implement the Hill Cypher
An Intro to Spring Cloud Security
Using Optional with Jackson
Java Program to Find Location of a Point Placed in Three Dimensions Using K-D Trees
Guide to ThreadLocalRandom in Java
Java Program to Create a Random Graph Using Random Edge Generation
Lớp Arrarys trong Java (Arrays Utility Class)
Inheritance and Composition (Is-a vs Has-a relationship) in Java