Java Programs›Java 8 Streams›Join Strings Using Collectors.joining()

Join Strings Using Collectors.joining() in Java

beginner·  Java 8 Streams  ·  Streams

Problem

Joining combines many strings into one, putting a separator between them and, optionally, a prefix before the first and a suffix after the last.

Given a list of tags, print them as a comma-separated line and as an upper-cased, bracketed list.

Input
[java, streams, collectors, interview]
Output
java, streams, collectors, interview

Java Program

Java
import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class JoinStringsUsingStreams { public static void main(String[] args) { List<String> tags = Arrays.asList("java", "streams", "collectors", "interview"); String plain = tags.stream().collect(Collectors.joining(", ")); String wrapped = tags.stream() .map(String::toUpperCase) .collect(Collectors.joining(" | ", "[", "]")); // separator, prefix, suffix System.out.println(plain); System.out.println(wrapped); } }

Output

java, streams, collectors, interview [JAVA | STREAMS | COLLECTORS | INTERVIEW]

Core Logic

Collectors.joining is the stream way to build a delimited string, and it fits naturally after a map step.

How It Works
  1. 1joining(", ") puts a comma and a space between elements, with nothing at the ends.
  2. 2map(String::toUpperCase) transforms each tag before it's joined.
  3. 3joining(" | ", "[", "]") adds a separator, a prefix and a suffix.
The second line becomes [JAVA | STREAMS | COLLECTORS | INTERVIEW].
💡

Key Point: Joining never adds a trailing separator, which avoids the classic "remove the last comma" fix-up of manual loops.

Complexity
Time Complexity: O(L)Space Complexity: O(L)

Why: Every character of the result, of total length L, is copied once into a builder.

Key Concepts

Collectors.joining()map()prefix and suffix

Approach 2: String.join and StringJoiner

Java
import java.util.Arrays; import java.util.List; import java.util.StringJoiner; public class JoinStringsStringJoin { public static void main(String[] args) { List<String> tags = Arrays.asList("java", "streams", "collectors", "interview"); System.out.println(String.join(", ", tags)); // simplest when no transformation is needed StringJoiner joiner = new StringJoiner(" | ", "[", "]"); joiner.setEmptyValue("(no tags)"); // printed if nothing is added for (String t : tags) joiner.add(t.toUpperCase()); System.out.println(joiner); System.out.println(new StringJoiner(", ", "[", "]").setEmptyValue("(no tags)")); } }

Output

java, streams, collectors, interview [JAVA | STREAMS | COLLECTORS | INTERVIEW] (no tags)

Core Logic

When no transformation is needed, String.join is simpler, and StringJoiner adds control such as a value for an empty result.

How It Works
  1. 1String.join(", ", tags) joins any Iterable of strings.
  2. 2StringJoiner takes the same separator, prefix and suffix as the collector.
  3. 3setEmptyValue("(no tags)") is returned when nothing was added.
The last line prints (no tags) because that joiner never received an element.
💡

Key Point: Collectors.joining is built on StringJoiner, so all three produce identical text.

Complexity
Time Complexity: O(L)Space Complexity: O(L)

Why: Each character of the result is appended once.

Key Concepts

String.join()StringJoinersetEmptyValue()

Interview Questions

Can Collectors.joining work on a stream of numbers?

Not directly — it needs CharSequence elements. Map the numbers first, for example map(String::valueOf).

Why not just use + in a loop?

Each + on a String creates a new object, so a loop is O(n²) in the worst case; joining uses one builder and stays linear.

Learn the Concept

Related Programs