Java 8 StringJoiner

1. Introduction

StringJoiner is a new class added in Java 8 under java.util package.

Simply put, it can be used for joining Strings making use of a delimiter, prefix, and suffix.

2. Adding Elements

We can add Strings using the add() method:

@Test
public void whenAddingElements_thenJoinedElements() {
    StringJoiner joiner = new StringJoiner(",", PREFIX, SUFFIX);
    joiner.add("Red")
      .add("Green")
      .add("Blue");

    assertEquals(joiner.toString(), "[Red,Green,Blue]");
}

If we want to join all elements of a list, we’ll have to loop through the list. Unfortunately, there’s no easy way to do it using StringJoiner:

@Test
public void whenAddingListElements_thenJoinedListElements() {
    List<String> rgbList = new ArrayList<>();
    rgbList.add("Red");
    rgbList.add("Green");
    rgbList.add("Blue");

    StringJoiner rgbJoiner = new StringJoiner(
      ",", PREFIX, SUFFIX);

    for (String color : rgbList) {
        rgbJoiner.add(color);
    }

    assertEquals(rgbJoiner.toString(), "[Red,Green,Blue]");
}

3. Construction

To construct an instance of StringJoiner, we need to mention the delimiter. Optionally, we can also specify the prefix and suffix that should be present in the result:

private String PREFIX = "[";
private String SUFFIX = "]";

@Test
public void whenEmptyJoinerWithoutPrefixSuffix_thenEmptyString() {
    StringJoiner joiner = new StringJoiner(",");
 
    assertEquals(0, joiner.toString().length());
}

@Test
public void whenEmptyJoinerJoinerWithPrefixSuffix_thenPrefixSuffix() {
    StringJoiner joiner = new StringJoiner(
      ",", PREFIX, SUFFIX);
 
    assertEquals(joiner.toString(), PREFIX + SUFFIX);
}

We use toString() to get the current value from the joiner.

Note default values returned by the joiners. Joiner without prefix and suffix returns an empty String whereas joiner with prefix and suffix returns a String containing both prefix and suffix.

We can change the default String returned by using setEmptyValue():

@Test
public void whenEmptyJoinerWithEmptyValue_thenDefaultValue() {
    StringJoiner joiner = new StringJoiner(",");
    joiner.setEmptyValue("default");

    assertEquals(joiner.toString(), "default");
}

@Test
public void whenEmptyJoinerWithPrefixSuffixAndEmptyValue_thenDefaultValue() {
    StringJoiner joiner = new StringJoiner(",", PREFIX, SUFFIX);
    joiner.setEmptyValue("default");

    assertEquals(joiner.toString(), "default");
}

Here, both joiners return the EMPTY_JOINER constant.

The default value is returned only when the StringJoiner is empty.

4. Merge Joiners

We can merge two joiners using merge(). It adds the contents of the given StringJoiner without prefix and suffix as the next element:

@Test
public void whenMergingJoiners_thenReturnMerged() {
    StringJoiner rgbJoiner = new StringJoiner(
      ",", PREFIX, SUFFIX);
    StringJoiner cmybJoiner = new StringJoiner(
      "-", PREFIX, SUFFIX);

    rgbJoiner.add("Red")
      .add("Green")
      .add("Blue");
    cmybJoiner.add("Cyan")
      .add("Magenta")
      .add("Yellow")
      .add("Black");

    rgbJoiner.merge(cmybJoiner);

    assertEquals(
      rgbJoiner.toString(), 
      "[Red,Green,Blue,Cyan-Magenta-Yellow-Black]");
}

Note how “-“ is used to concatenate content of cmybJoiner while rgbJoiner still use “,”.

5. Stream API

That’s pretty much all that we can do with StringJoiner.

There’s one more indirect usage that can be found in the Stream API:

@Test
public void whenUsedWithinCollectors_thenJoined() {
    List<String> rgbList = Arrays.asList("Red", "Green", "Blue");
    String commaSeparatedRGB = rgbList.stream()
      .map(color -> color.toString())
      .collect(Collectors.joining(","));

    assertEquals(commaSeparatedRGB, "Red,Green,Blue");
}

Collectors.joining() internally uses StringJoiner to perform the joining operation.

6. Conclusion

In this quick tutorial, we illustrated how to use the StringJoiner class. Overall the StringJoiner seems very primitive and fails to address some basic use cases like joining the elements of a list. It seems to be primarily designed for Collectors.

If StringJoiner doesn’t meet our requirements, there are other popular and powerful libraries, such as Guava.

And, as usual, all sources can be found over on GitHub.