streamex icon indicating copy to clipboard operation
streamex copied to clipboard

Joining collector: possibility to specify custom delimiter used before the last stream element

Open amaembo opened this issue 8 years ago • 2 comments

A custom delimiter could be specified to format more user-friendly messages like this:

StreamEx.of("Red", "Green", "Blue", "Black").collect(
         Joining.with(", ").lastDelimiter(" or "));
// Produces "Red, Green, Blue or Black"

Possible names for new method: lastDelimiter, beforeLast. An open question is whether it should be used when short-circuit occurs.

amaembo avatar Nov 13 '15 07:11 amaembo

A work around for this is...

StreamEx.
   of("Red", "Green", "Blue", "Black").
   collect(Joining.with(", ").lastDelimiter(" or ")).
   replaceFirst("^(.+), (.*)$", "$1 or $2");

The first group in the regular expression is greedy and will try to match the whole string. It will then have to backup until the ", " is found. Thus, the last ", " will be found and replaced with " or ".

This regular expression assumes that ", " will not appear in any of the strings being joined.

numeralnathan avatar Oct 28 '16 17:10 numeralnathan

@nathanila, actually Joining collector is much more smart. For example, it can short-circuit based on maximal string length, cutting at character/codepoint/grapheme/word bound, etc. It's actually the hardest part here: how to properly combine this lastDelimiter feature with all the existing features. Replacing last delimiter with ", " with " or " may increase the line length exceeding the maximal allowed length. Also it's not semantically equivalent even without length limit. Consider the following input:

List<String> movies = asList("Snatch", "Revolver", "Locks, Stocks and Two Smoking Barrels");
System.out.println("Which movie do you want to see: "+
    StreamEx.of(movies).map(m -> '"'+m+'"').collect(
        Joining.with(", ").lastDelimiter(" or "))+"?");

I mean if the string contains the delimiter, the regexp will screw the things up. In general regexps should be used with caution: with unexpected input (unintentional or malicious) they may break your program.

amaembo avatar Oct 29 '16 02:10 amaembo