Joining Strings from a Stream

Streams · lesson 22 of 42 · 3 min read

Build a separated, wrapped string in one pass, with no StringBuilder and no trailing comma.

Open this lesson in the learning hub

Key points

  • Collectors.joining() glues elements together. The three argument form adds a separator, a prefix and a suffix.
  • It handles the trailing separator problem for you, which is where hand written loops usually go wrong.
  • On an empty stream the three argument form still emits the prefix and suffix, so you get an empty pair of brackets.
  • It only accepts CharSequence, so map numbers and objects to text first with map(Object::toString).
  • No stream in play? String.join(sep, collection) does the same job with less ceremony.
  • As a downstream collector inside groupingBy it builds one report line per group in a single pass.

Example

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        List<String> langs = List.of("Java", "Kotlin", "Scala");

        System.out.println("plain    : " + langs.stream().collect(Collectors.joining()));
        System.out.println("commas   : " + langs.stream().collect(Collectors.joining(", ")));
        System.out.println("wrapped  : " + langs.stream().collect(Collectors.joining(", ", "[", "]")));
        System.out.println("empty    : " + Stream.<String>empty().collect(Collectors.joining(", ", "[", "]")));

        // No stream in play? String.join does the same job with less ceremony.
        System.out.println("String   : " + String.join(" | ", langs));

        // joining only accepts CharSequence, so map numbers to text first.
        System.out.println("ids      : " + IntStream.rangeClosed(1, 4)
                .mapToObj(Integer::toString).collect(Collectors.joining("-")));

        // As a downstream collector it builds one report line per group.
        Map<Integer, String> byLength = langs.stream().collect(Collectors.groupingBy(
                String::length, TreeMap::new, Collectors.joining(" & ")));
        System.out.println("grouped  : " + byLength);
    }
}

joining is the trailing comma bug you never have to fix again.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Streams course, and every lesson in it is listed on the Streams contents page.