Taking a list of items and transforming them into a String with delimiters between each item and possibly prefixes and suffixes, is a common need in software development. It’s also a frequent source of frustration as the below code example demonstrates.
List<String> devAdvocates = List.of("Billy", "David", "Denys", "José", "Nicolai");
StringBuilder devAdvocateList = new StringBuilder();
devAdvocateList.append("{ ");
for(String devAdvocate : devAdvocates) {
devAdvocateList.append(devAdvocate);
devAdvocateList.append(", ");
}
devAdvocateList.append(" }");
System.out.println(devAdvocateList);
{ Billy, David, Denys, José, Nicolai, }
Manually having to add the prefix and suffix before and after a loop statement is messy. There is also the issue of dealingwith the final delimiter instance, which often requires adding logic to a loop to skip adding the delimiter after the last time, or messy editing of the String to remove the final delimiter.
Luckily there is a much easier way of handling this, the Join APIs, all of which are avaiable in JDK 8!
StringJoiner
has two constructors, one taking only a delimiter, a second that takes a prefix and suffix. Items can be add to a StringJoiner
individually using add()
like in the example below:
List<String> devAdvocates = List.of("Billy", "David", "Denys", "José", "Nicolai");
StringJoiner joiner = new StringJoiner(", ", "{ ", " }");
for(String devAdvocate : devAdvocates) {
joiner.add(devAdvocate);
}
System.out.println(joiner.toString());
{ Billy, David, Denys, José, Nicolai }
If the items being transformed to a String are already in an Iterable
instance, like in the example below using List
(which extends Iterable
), then all the items can be added in a single call with forEach
and using the StringJoiner::add
method reference like in the below example:
List<String> devAdvocates = List.of("Billy", "David", "Denys", "José", "Nicolai");
StringJoiner joiner = new StringJoiner(", ", "{ ", " }");
devAdvocates.forEach(joiner::add);
System.out.println(joiner.toString());
If you prefer to use a Stream
consider using Collectors.joining()
. Like with StringJoiner
, Collectors.joining()
can either take just a delimiter, or a prefix and suffix. The below demonstrates using Collectors.joining()
:
List<String> devAdvocates = List.of("Billy", "David", "Denys", "José", "Nicolai");
String devAdvocatesList = devAdvocates.stream().collect(Collectors.joining(", ", "{ ", " }"));
System.out.println(devAdvocatesList);
If you only need to use a delimiter in the String list being built, String.join()
might be the best option. String.join()
can accept an Iterable
like in the below example:
List<String> devAdvocates = List.of("Billy", "David", "Denys", "José", "Nicolai");
System.out.println(String.join(", ", devAdvocates));
Billy, David, Denys, José, Nicolai
String.join()
can also take a varargs of items like shown here:
System.out.println(String.join(", ", "Billy", "David", "Denys", "José", "Nicolai"));
Happy coding!