streamex
streamex copied to clipboard
Joining collector: possibility to specify custom delimiter used before the last stream element
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.
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.
@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.