StringJoiner in b88
Brian Goetz
brian.goetz at oracle.com
Fri May 17 07:28:14 PDT 2013
Yes, this is a regrettable weakness of Collector which I spent some time
trying to address and ultimately concluded it wasn't worth the added
complexity.
Here's the problem: the delimiter version of StringJoiner is basically a
sequential construct. When we parallelize a mutable reduction, the
Collector primitives are:
- make new result container
- incorporate a new result into the container
- merge two containers
The invariant that is the equivalent of the associativity constraint for
reduction is:
add(new(), t1, t2) == combine(add(new(), t1), add(new(), t2))
Stringjoiner with no prefix/suffix meets these rules; we can create two
StringJoiners and stuff elements into them:
sj1: a, b, c, d
sj2: e, f, g, h
and then combine them with sj1.add(sj2):
sj1: a, b, c, d, e, f, g, h
With prefix/suffix, it does not, because we'd have extra prefixes and
suffixes:
sj1: [ a, b, c, d ]
sj2: [ e, f, g, h ]
joined: [ a, b, c, d, [ e, f, g, h ] ]
In order to fix this, Collector would have to know whether we're at the
root of the computation tree, and if so, invoke new with different
parameters.
The workaround is simple, but not as pretty as you want:
StringJoiner sj = new StringJoiner(",", "[", "]");
stream.blah.blah.blah.forEach(sj::add);
String result = sj.toString();
In other words, you can still do exactly what you want with relatively
few additional lines of code, but the penalty is dropping out of the
fluent model.
On 5/17/2013 3:32 AM, Joe Bowbeer wrote:
> Previously, when StringJoiner was a stream destination, I could collect
> into one using the three-arg variant:
>
> s.into(new StringJoiner(delimiter, prefix, suffix));
>
> For example:
>
> elements.into(new StringJoiner(", ", "[", "]"));
>
> But I can't now because Collectors.toStringJoiner(delimiter) is the only
> option.
>
> What's the recommended workaround?
>
> Should Collectors.toStringJoiner(delimiter, prefix, suffix) be added?
>
>
>
> On Mon, May 6, 2013 at 5:56 AM, Brian Goetz <brian.goetz at oracle.com
> <mailto:brian.goetz at oracle.com>> wrote:
>
> There has not been a "stream destination" type or an "into" method
> for a very long time.
>
> But, if you want to use a string joiner as a stream target, do:
>
> stream.collect(toStringJoiner(__));
>
>
> On 5/6/2013 3:19 AM, Joe Bowbeer wrote:
>
> In b88, StringJoiner does not implement a stream destination?
>
> Is the "into" example in the javadoc no longer valid?
>
> http://download.java.net/__lambda/b88/docs/api/java/util/__StringJoiner.html
> <http://download.java.net/lambda/b88/docs/api/java/util/StringJoiner.html>
>
> Joe
>
>
More information about the lambda-libs-spec-experts
mailing list