How can i reduce or collect a list of string delimitted by comma and prefixed "and" only to the last element using Java 8 Streams?
eg.
List<String> ls = Arrays.asList("tom","terry","john","kevin","steve");
String result = ls.stream().map(String::toString)
.collect(Collectors.joining(", "));
System.out.println(result);
This statement prints => tom, terry, john, kevin, steve. But i wanted to print the list as tom, terry, john, kevin and steve.
Two solutions.
Clumsy, taking sublist actually:
String result = ls.stream()
.limit(ls.size() - 1)
.collect(Collectors.joining(", ")) + " and " + ls.get(ls.size() - 1);
Using a class to shift one place:
class SbS {
StringBuilder sb = new StringBuilder();
String s = "";
@Override
public String toString() {
return sb + (s.empty() ? "" : " and " + s);
}
}
result = ls.stream()
.collect(SbS::new,
(a, s) -> {
a.sb.append(a.sb.length() == 0 ? "" : ", ").append(a.s); a.s = s;
},
(a1, a2) -> {}).toString();
Mind: the class definition should be placed inside the method, just as above. Otherwise static
would be needed. The lambda for the (a, s)
could be a method in SbS. The support for parallelism is left as excercise to the reader (a1, a1)
.