How often do you have an array of strings:
List<String> listOfStrings = Lists.newArrayList("egg", "apple", null, "pineapple", "orange");
and needed to join its items in one string separated with commas (avoiding nulls) like that:
egg, apple, pineapple, orange
Source Code for this Guide is on my github: https://github.com/yacekmm/looksok/tree/master/Guava/GettingStarted
Doing it Java way
And how often did you use foreach loop and StringBuilder for it? Oh… and don’t forget to remove the last separator when you’re finished :) We see the code like that quite often, right?
StringBuilder builder = new StringBuilder(); for (String item : listOfStrings){ if(item != null) { builder.append(item).append(SEPARATOR); } } builder.setLength(builder.length() - SEPARATOR.length()); //remove last SEPARATOR
With Java 8 it can be a bit simplier:
String result = listOfStrings.stream() .filter( item -> item != null) .reduce((s, s2) -> s + SEPARATOR + s2) .get();
Joining with Guava in one line
With Guava this is even shorter:
String result = Joiner.on(SEPARATOR).skipNulls().join(listOfStrings);
All in one line. No trailing separator that needs to be removed. Perfect – from now on you should never do it again without Guava :)
Can only Strings be Joined?
No – the toString() method will be called on each item of provided array. This way any custom object can be Joined.
Replacing null items in array with custom value
In previous example the null was ignored. Here is how to replace null with default value:
String result = Joiner.on(SEPARATOR).useForNull("EMPTY VALUE").join(listOfStrings);
Now the result will be:
egg, apple, EMPTY VALUE, pineapple, orange
Enhancing the Appendable object with more items
Joiner can be used with classes that implement Appendable interface (e.g. StringBuilder, FilewWriter) and append more items to it:
String result = Joiner.on(SEPARATOR).skipNulls().join(listOfStrings); StringBuilder builder = new StringBuilder(result); String extendedResult = Joiner.on(SEPARATOR).skipNulls().join(builder, "Strawberry");
The result is:
egg, apple, pineapple, orange, Strawberry
Joining the maps with custom key-value separator
I have a map:
Map<String, Integer> map
That holds a String as a key, and its length as a value. I can join items in this map easily with Joiner class, providing the key-value separator:
Joiner.on(SEPARATOR + "\n\t").withKeyValueSeparator(" has length of: ").join(map);
The result string is:
orange has length of: 6, apple has length of: 5, egg has length of: 3, pineapple has length of: 9
Source Code for this Guide is on my github: https://github.com/yacekmm/looksok/tree/master/Guava/GettingStarted
I think one point is missing related to plain Java. Since Java 8 there is StringJoiner class in Java SDK that can be used for joining Strings, e.g. you can use this class as a collector in a stream in order to join all the collections elements.
https://docs.oracle.com/javase/8/docs/api/java/util/StringJoiner.html
Yes, perfectly noticed! That’s why i really like doing that blog – I have a chance to learn more.
With each consecutive Java version release Guava features seems to be more and more incorporated into JDK. Which seems to be technical debt fixing and I… tend to like it :)
I really want to know more about the StringJoiner but this does not fit that post in my opinion. I’ll do it in separate article – stay tuned!