Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why StringJoiner when we already have StringBuilder?

I recently encountered with a Java 8 class StringJoiner which adds the String using the delimiters and adds prefix and suffix to it, but I can't understand the need of this class as it also uses StringBuilder at the backend and also performs very simple operation of appending the Strings.

Am I missing something by not actually understanding the real purpose of this class?

like image 744
Hitesh Garg Avatar asked Dec 17 '14 09:12

Hitesh Garg


People also ask

What is the difference between StringBuilder and StringJoiner?

StringJoiner vs StringBuilderStringJoiner makes joining strings easy, as compared to StringBuilder. If you have to join strings from StringBuilder , then you will append each string and delimiter in alternate sequence. And do not forget to remove delimiter appended to last of final string, if it there.

Why is StringBuffer less efficient than StringBuilder?

StringBuffer is thread-safe and synchronized whereas StringBuilder is not. That's why StringBuilder is faster than StringBuffer. String concatenation operator (+) internally uses StringBuffer or StringBuilder class.

Is StringJoiner thread-safe?

Unlike StringBuffer methods (like append() ) which are synchronized, methods of StringJoiner (like add() ) are not synchronized . Thus it is not thread-safe. Source code from OpenJDK: StringJoiner.

What is the best reason for using string builder instead of string?

This is because String is immutable - it cannot change its internal state. On the other hand StringBuilder is mutable. When you call append(..) it alters the internal char array, rather than creating a new string object.


2 Answers

StringJoiner is very useful, when you need to join Strings in a Stream.

As an example, if you have to following List of Strings:

final List<String> strings = Arrays.asList("Foo", "Bar", "Baz");

It is much more simpler to use

final String collectJoin = strings.stream().collect(Collectors.joining(", "));

as it would be with a StringBuilder:

final String collectBuilder =
    strings.stream().collect(Collector.of(StringBuilder::new,
        (stringBuilder, str) -> stringBuilder.append(str).append(", "),
        StringBuilder::append,
        StringBuilder::toString));

EDIT 6 years later As noted in the comments, there are now much simpler solutions like String.join(", ", strings), which were not available back then. But the use case is still the same.

like image 153
Martin Seeler Avatar answered Oct 21 '22 09:10

Martin Seeler


The examples on the StringJoiner Javadoc are very good at covering this. The whole point to to abstract away the choice of seperator from the act of adding entries. e.g. you can create a joiner, specify the seperator to use and pass it to a library to do the adding of elements or visa versa.

The String "[George:Sally:Fred]" may be constructed as follows:

StringJoiner sj = new StringJoiner(":", "[", "]");
sj.add("George").add("Sally").add("Fred");
String desiredString = sj.toString();

A StringJoiner may be employed to create formatted output from a Stream using Collectors.joining(CharSequence). For example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
String commaSeparatedNumbers = numbers.stream()
    .map(i -> i.toString())
    .collect(Collectors.joining(", "));
like image 23
Peter Lawrey Avatar answered Oct 21 '22 09:10

Peter Lawrey