I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE COURSE

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. A 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.

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE LESSONS

newest oldest most voted
Hamish Lawson
Guest
Hamish Lawson

Looping through rgbList can be avoided by using the String.join() method, also added in Java 8, which internally makes use of StringJoiner:

String.join(“,”, rgbList)

Granted, this doesn’t have provision for enclosing the string with PREFIX and SUFFIX, but those can easily be added afterwards.

Torsten
Guest
Torsten

yes, that’s possible, but it breaks the nice API ’cause you have to pass the delimiter twice and you’re doing the whole joining outside the StringJoiner. .

why not just use the following snippet:

rgbList.foreach(rgbJoiner::add);

JoeHx
Guest

I really like StringJoiner, and it’s nice to use something without adding an entire external dependency.