Joining strings with Java 8's StringJoiner

In this article, we present the new Java 8 API for joining strings. Java was lacking API for simple joining of strings for years. In Java 8, the StringJoiner was introduced.

StringJoiner is used to construct a sequence of characters separated by a delimiter and optionally starting with a supplied prefix and ending with a supplied suffix.

StringJoiner is also used internally by the join() method of the String class.

Using StringJoiner

The following example joins numbers with the StringJoiner class.

Java8StringJoinEx.java
package com.zetcode;

import java.util.StringJoiner;

public class Java8StringJoinEx {

    public static void main(String[] args) {

        StringJoiner join = new StringJoiner(",");
        join.add("1");
        join.add("2");
        join.add("3");
        join.add("4");
        join.add("5");
        
        System.out.println(join);
    }
}

The example concatenates five numbers and prints the final string to the console.

StringJoiner join = new StringJoiner(",");

A new instance of the StringJoiner class is created. The comma character is used as a delimiter.

join.add("1");
join.add("2");
join.add("3");
join.add("4");
join.add("5");

Five values are added with the add() method.

System.out.println(join);

The StringJoiner is converted to a string and printed to the console.

$ java com.zetcode.Java8StringJoinEx 
1,2,3,4,5

This is the output of the example.

The String.join() method

In the second example, we join strings with the String.join() method.

Java8StringJoinEx2.java
package com.zetcode;

public class Java8StringJoinEx2 {

    public static void main(String[] args) {

        String join = String.join("/", "2016", "8", "5");
        System.out.println(join);
    }
}

The String.join() method internally uses the StringJoiner.

String join = String.join("/", "2016", "8", "5");

A date is concatenated with the String.join() method.

$ java com.zetcode.Java8StringJoinEx2 
2016/8/5

This is the output of the example.

Joining list

The third example concatenates elements of a list.

Java8StringJoinEx3.java
package com.zetcode;

import java.util.Arrays;
import java.util.List;

public class Java8StringJoinEx3 {

    public static void main(String[] args) {

        List<String> list = Arrays.asList("Today", "is", "a", "beautiful", "day");
        String joined = String.join(" ", list); 
        
        System.out.println(joined);
    }
}

A list can be passed as an argument to the String.join() method.

String joined = String.join(" ", list); 

The elements of the list are joined with a single space character.

$ java com.zetcode.Java8StringJoinEx3 
Today is a beautiful day

The elements of a list were concatenated to create a sentence.

Reading CSV file

The following example reads numbers from a CSV file and later joins them with a StringJoiner. We use the Gradle build tool to build the example.

$ tree
.
├── build.gradle
└── src
    └── main
        ├── java
        │   └── com
        │       └── zetcode
        │           └── Java8StringJoinEx4.java
        └── resources
            └── numbers.csv

6 directories, 3 files

The example has his project structure. The numbers that we are going to read are located in the resources directory.

build.gradle
version '1.0'

apply plugin: 'java'
apply plugin: 'application'

sourceCompatibility = 1.8

mainClassName = "com.zetcode.Java8StringJoinEx4"

This is the Gradle build file.

numbers.csv
13,24,35,16,50

This is the numbers.csv file.

Java8StringJoinEx4.java
package com.zetcode;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.StringJoiner;

public class Java8StringJoinEx4 {

    public static void main(String[] args) throws FileNotFoundException {

        Scanner scanner = new Scanner(new File("src/main/resources/numbers.csv"));
        scanner.useDelimiter(",");

        StringJoiner join = new StringJoiner("|");

        while (scanner.hasNext()) {
        
            join.add(scanner.next());
        }
        
        scanner.close();
        
        System.out.println(join);
    }
}

The example reads CSV file, containing numbers, and joins them with a StringJoiner using a different delimiter.

Scanner scanner = new Scanner(new File("src/main/resources/numbers.csv"));
scanner.useDelimiter(",");

The values are read with the Scanner class. The numbers are separated by a comma character so we set the comma delimiter with the useDelimiter() method.

StringJoiner join = new StringJoiner("|");

A StringJoiner class is instantiated with a "|" delimiter.

while (scanner.hasNext()) {

    join.add(scanner.next());
}

We retrieve the values with the scanner and concatenate them with the joiner.

$ gradle build
:compileJava
:processResources
:classes
:jar
:startScripts
:distTar
:distZip
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

We build the project with the gradle build command.

$ gradle run
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
13|24|35|16|50

We run the application with the gradle run command. The last line is the output of our application.

Writing CSV file

The next example writes numbers to a CSV file.

$ tree
.
├── build.gradle
└── src
    └── main
        └── java
            └── com
                └── zetcode
                    └── Java8StringJoinEx5.java

The example has his project structure. We are going to create a new file in the current working directory.

build.gradle
version '1.0'

apply plugin: 'java'
apply plugin: 'application'

sourceCompatibility = 1.8

mainClassName = "com.zetcode.Java8StringJoinEx5"

This is the Gradle build file.

Java8StringJoinEx5.java
package com.zetcode;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.StringJoiner;

public class Java8StringJoinEx5 {

    public static void main(String[] args) throws FileNotFoundException, 
            IOException {

        StringJoiner join = new StringJoiner(",");
        join.add("21");
        join.add("43");
        join.add("54");
        join.add("76");
        join.add("98");
        
        File newFile = new File("numbers2.csv");
        newFile.createNewFile();

        PrintWriter pw = new PrintWriter(newFile);
        pw.write(join.toString());
        pw.close();
    }
}

The example joins five numbers with a StringJoiner and writes the concatendated string to a CSV file.

StringJoiner join = new StringJoiner(",");
join.add("21");
join.add("43");
join.add("54");
join.add("76");
join.add("98");

Five numbers are concatenated with the StringJoiner. The numbers are separated with a comma character.

File newFile = new File("numbers.csv");
newFile.createNewFile();

A new file object is created in the current working directory.

File newFile = new File("numbers.csv");
newFile.createNewFile();

A new file object is created in the current working directory.

PrintWriter pw = new PrintWriter(newFile);
pw.write(join.toString());
pw.close();

The joined values are written to the file.

$ gradle build run

We build and run the application.

$ cat numbers2.csv 
21,43,54,76,98

We show the contents of the created file.

Collectors.joining()

Java 8 has also introduced the Collectors.joining() method in the new stream API. The method returns a Collector that concatenates the input elements, separated by the specified delimiter, in encounter order.

Java8CollectorJoiningEx.java
package com.zetcode;

import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Java8CollectorJoiningEx {

    public static void main(String[] args) {

        Stream<String> stream = Stream.of("Jan", "Peter", "Robert");

        String names = stream.collect(Collectors.joining(" "));

        System.out.println(names);
    }
}

The example uses the stream API to concatenate three names.

$ java com.zetcode.Java8CollectorJoiningEx 
Jan Peter Robert

This is the output of the example.

In this article, we have worked with the StringJoiner, the new class introduced in Java 8. We have also added a small example showing the new Collectors.joining() from the stream API.

You might also be interested in the following related tutorials: Java tutorial, Java 8 forEach tutorial, Introduction to Google Guava, Filtering a list in Java, or Android tutorial.