使用 Java 8 Streams 减少字符串列表,仅将前缀添加到最后一个元素
Reduce a list of string add prefix only to last element using Java 8 Streams
如何使用 Java 8 Streams 减少或收集以逗号分隔并仅在最后一个元素前加上 "and" 前缀的字符串列表?
例如。
List<String> ls = Arrays.asList("tom","terry","john","kevin","steve");
String result = ls.stream().map(String::toString)
.collect(Collectors.joining(", "));
System.out.println(result);
此语句打印 => 汤姆、特里、约翰、凯文、史蒂夫。但我想将列表打印为 tom、terry、john、kevin 和 steve。
流并没有使这变得更容易。你也可以使用 String::replaceAll
:
String input = "tom, terry, john, kevin, steve";
String result = input.replaceAll(", (\w+)$", " and ");
System.out.println(result);
输出:
tom, terry, john, kevin and steve
两种解决方案。
笨手笨脚,居然取子列表:
String result = ls.stream()
.limit(ls.size() - 1)
.collect(Collectors.joining(", ")) + " and " + ls.get(ls.size() - 1);
使用class移动一位:
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();
注意:class 定义应该放在方法内部,就像上面一样。否则将需要 static
。 (a, s)
的 lambda 可能是 SbS 中的一种方法。对并行性的支持留作 reader (a1, a1)
.
的练习
Stream API 没有提供实现此目的的标准方法。我的 StreamEx library which extends standard Stream API has a mapLast
方法在这里很有用。它只允许映射最后一个流元素,其他所有元素保持原样:
System.out.println(StreamEx.of(ls).mapLast("and "::concat).joining(", "));
结果如下:
tom, terry, john, kevin, and steve
请注意,它在 "and" 之前添加了一个逗号,这是可以的(请参阅 Oxford Comma)。如果你不喜欢它(或者实际上使用另一种禁止这种标点符号的语言),那么它可以用稍微长一点的方式来实现:
StreamEx.of(ls)
.mapLastOrElse(", "::concat, " and "::concat)
.joining().substring(", ".length());
如何使用 Java 8 Streams 减少或收集以逗号分隔并仅在最后一个元素前加上 "and" 前缀的字符串列表?
例如。
List<String> ls = Arrays.asList("tom","terry","john","kevin","steve");
String result = ls.stream().map(String::toString)
.collect(Collectors.joining(", "));
System.out.println(result);
此语句打印 => 汤姆、特里、约翰、凯文、史蒂夫。但我想将列表打印为 tom、terry、john、kevin 和 steve。
流并没有使这变得更容易。你也可以使用 String::replaceAll
:
String input = "tom, terry, john, kevin, steve";
String result = input.replaceAll(", (\w+)$", " and ");
System.out.println(result);
输出:
tom, terry, john, kevin and steve
两种解决方案。
笨手笨脚,居然取子列表:
String result = ls.stream()
.limit(ls.size() - 1)
.collect(Collectors.joining(", ")) + " and " + ls.get(ls.size() - 1);
使用class移动一位:
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();
注意:class 定义应该放在方法内部,就像上面一样。否则将需要 static
。 (a, s)
的 lambda 可能是 SbS 中的一种方法。对并行性的支持留作 reader (a1, a1)
.
Stream API 没有提供实现此目的的标准方法。我的 StreamEx library which extends standard Stream API has a mapLast
方法在这里很有用。它只允许映射最后一个流元素,其他所有元素保持原样:
System.out.println(StreamEx.of(ls).mapLast("and "::concat).joining(", "));
结果如下:
tom, terry, john, kevin, and steve
请注意,它在 "and" 之前添加了一个逗号,这是可以的(请参阅 Oxford Comma)。如果你不喜欢它(或者实际上使用另一种禁止这种标点符号的语言),那么它可以用稍微长一点的方式来实现:
StreamEx.of(ls)
.mapLastOrElse(", "::concat, " and "::concat)
.joining().substring(", ".length());