Using stream.collect(Collectors.joining(\", \")) I can easily join all the strings of my stream delimited by a comma. A possible result would be \"a, b, c
If they are already in a list, no stream is needed; simply join a sublist of all but the last element and concat the other delimiter and the final element:
int last = list.size() - 1;
String joined = String.join(" and ",
String.join(", ", list.subList(0, last)),
list.get(last));
Here's a version that does the above using Collectors.collectingAndThen:
stream.collect(Collectors.collectingAndThen(Collectors.toList(),
joiningLastDelimiter(", ", " and ")));
public static Function, String> joiningLastDelimiter(
String delimiter, String lastDelimiter) {
return list -> {
int last = list.size() - 1;
if (last < 1) return String.join(delimiter, list);
return String.join(lastDelimiter,
String.join(delimiter, list.subList(0, last)),
list.get(last));
};
}
This version can also handle the case where the stream is empty or only has one value. Thanks to Holger and Andreas for their suggestions which greatly improved this solution.
I had suggested in a comment that the Oxford comma could be accomplished with this using ", " and ", and" as the delimiters, but that yields incorrect results of "a, and b" for two elements, so just for fun here's one that does Oxford commas correctly:
stream.collect(Collectors.collectingAndThen(Collectors.toList(),
joiningOxfordComma()));
public static Function, String> joiningOxfordComma() {
return list -> {
int last = list.size() - 1;
if (last < 1) return String.join("", list);
if (last == 1) return String.join(" and ", list);
return String.join(", and ",
String.join(", ", list.subList(0, last)),
list.get(last));
};
}