00:00

StringJoiner in Java – Joining Strings with Delimiters

java.util.StringJoiner, added in Java 8, builds a string from a sequence of values separated by a delimiter, optionally wrapped in a prefix and suffix. It removes the classic "trailing comma" problem of manual concatenation and powers String.join and Collectors.joining behind the scenes.

This tutorial covers its constructors and methods, empty values, merging joiners, and the related joining APIs you will use most often.

1. Constructors and Methods

Constructor / methodDescription
StringJoiner(CharSequence delimiter)Joiner with a delimiter only
StringJoiner(delimiter, prefix, suffix)Also wraps the result
add(CharSequence)Appends a value; returns the joiner for chaining
setEmptyValue(CharSequence)Text returned when nothing has been added
merge(StringJoiner other)Adds another joiner's content as one element
length()Length of the current result
toString()The joined string

2. Joining with Delimiter, Prefix and Suffix

JoinerBasics.java
import java.util.StringJoiner;

public class JoinerBasics {
    public static void main(String[] args) {
        // Delimiter only
        StringJoiner langs = new StringJoiner(", ");
        langs.add("Java").add("Kotlin").add("Scala");          // add() returns the joiner
        System.out.println(langs);

        // Delimiter, prefix and suffix
        StringJoiner json = new StringJoiner(", ", "[", "]");
        for (String id : new String[] {"\"A-17\"", "\"B-42\"", "\"C-99\""}) json.add(id);
        System.out.println(json + "  (length " + json.length() + ")");

        // Empty joiner: prefix + suffix by default, or a custom empty value
        StringJoiner none = new StringJoiner(", ", "{", "}");
        System.out.println("empty default: " + none);
        none.setEmptyValue("no items");
        System.out.println("empty custom:  " + none);
        none.add("pen");
        System.out.println("after add:     " + none);
    }
}
Output
Java, Kotlin, Scala
["A-17", "B-42", "C-99"]  (length 24)
empty default: {}
empty custom:  no items
after add:     {pen}
  • The delimiter appears only between elements, so there is no trailing separator to remove.
  • An empty joiner returns prefix + suffix unless setEmptyValue was called.
  • Adding null appends the text "null".

3. Merging Joiners

MergeJoiners.java
import java.util.StringJoiner;

public class MergeJoiners {
    public static void main(String[] args) {
        StringJoiner backend = new StringJoiner(", ", "Backend[", "]");
        backend.add("Java").add("Go");
        StringJoiner frontend = new StringJoiner(" | ", "Frontend(", ")");
        frontend.add("React").add("Angular");

        // merge() adds the other joiner's CONTENT (without its prefix/suffix) as one element
        backend.merge(frontend);
        System.out.println(backend);
    }
}
Output
Backend[Java, Go, React | Angular]

merge takes the other joiner's content without its prefix and suffix and adds it as a single element using this joiner's delimiter. The other joiner is unchanged.

4. String.join and Collectors.joining

In everyday code you often use the higher-level APIs built on StringJoiner:

JoinAlternatives.java
import java.util.List;
import java.util.stream.Collectors;

public class JoinAlternatives {
    record City(String name, int population) { }

    public static void main(String[] args) {
        List<String> tags = List.of("java", "spring", "kafka");
        System.out.println(String.join(" #", tags));                       // String.join (uses StringJoiner)

        List<City> cities = List.of(new City("Mumbai", 20), new City("Pune", 7), new City("Kochi", 2));
        String big = cities.stream()
                .filter(c -> c.population() > 5)
                .map(City::name)
                .collect(Collectors.joining(", ", "Big cities: ", "."));     // Collectors.joining
        System.out.println(big);

        String sql = "SELECT * FROM users WHERE id IN "
                + List.of(3, 8, 15).stream().map(String::valueOf).collect(Collectors.joining(", ", "(", ")"));
        System.out.println(sql);
    }
}
Output
java #spring #kafka
Big cities: Mumbai, Pune.
SELECT * FROM users WHERE id IN (3, 8, 15)
ToolBest for
String.join(delim, elements)Joining an array or Iterable of strings in one call
Collectors.joining(delim, prefix, suffix)Joining at the end of a stream pipeline
StringJoinerAdding values gradually, conditionally, or when you need setEmptyValue/merge
StringBuilderGeneral string building without a regular delimiter
Note: building SQL by joining values, as in the example, is fine for trusted numeric IDs only. For user input, always use PreparedStatement parameters to avoid SQL injection.

5. Summary

  • StringJoiner joins values with a delimiter and optional prefix and suffix.
  • setEmptyValue controls the result when nothing is added; merge combines joiners.
  • String.join and Collectors.joining are convenient front-ends built on it.
  • It avoids manual trailing-delimiter handling, making code shorter and clearer.

Related Tutorials