-
Notifications
You must be signed in to change notification settings - Fork 65
Joiner Explained
Why Joiner
when Guava already has Joiner?
Starting from Java 8, the JDK joining()
collector has more or less superseded Guava Joiner
for the primary intended use case. Joiner
is slightly more convenient in that it can join Object
while JDK joining()
can only join strings. There are also auxiliary functionalities in Joiner that aren't directly provided by JDK, such as MapJoiner
, skipNulls()
etc. However those alone no longer satisfy the high barrier of entry for Guava inclusion.
Guava is unlikely to deprecate Joiner, but it's unlikely to evolve either.
Mug Joiner
is implemented as a first-class Collector
so you can directly use it in streams: stream.collect(Joiner.on(','))
.
Similar to Guava Joiner
, it can join Object
and provides skipNulls()
. In addition, we provide fluent methods such as between()
, skipEmpties()
etc.
From what we've learned internally, the JDK joining(String, String, String)
collector that supports prefix and suffix is prone to misuse. Some may intuitively expect to call it like joining("{", ",", "}")
following the encounter order of delimiters; except JDK's ordering is joining(",", "{", "}")
. Using between()
, it can be expressed fluently with no ambiguity: Joiner.on(',').between('{', '}')
.
The binary join(Object, Object)
can be used in a BiStream
to combine the pair, as in:
BiStream.zip(ids, names)
.mapToObj(Joiner.on(':')::join)
While you can do the same with Guava's Joiner
too, the dedicated binary join()
is more efficient as it doesn't create temporary arrays and lists.
We expect Mug Joiner
to provide all functionalities you need. You won't need to use Guava Joiner any more.
When you have a Map
, Multimap
or BiStream
, joining the entries is as easy as:
// {k1=v1, k2=v2, ...}
BiStream.from(map)
.mapToObj(Joiner.on('=')::join)
.collect(Joiner.on(", ").between('{', '}'));
It's more readable than MapJoiner
because you can provide the delimiters in a consistent ordering: from inside out. That is, first you set the delimiter for each individual pair, then the delimiter between pairs, and finally the prefix and suffix of the entire string.
That said, if you truly want to combine them together, for example in a reusable BiCollector
, you can do so easily as in:
static BiCollector<Object, Object, String> toMapString() {
return BiCollectors.mapping(Joiner.on('=')::join, Joiner.on(", ").between('{', '}'));
}