加入具有不同最后分隔符的字符串

使用stream.collect(Collectors.joining(", "))我可以轻松地加入由逗号分隔的流的所有字符串。 可能的结果是"a, b, c" 。 但是,如果我希望最后一个分隔符不同,该怎么办? 例如,为" and " ,以便得到"a, b and c"作为结果。 有一个简单的解决方案吗?

如果它们已经在列表中,则不需要流; 只需加入除最后一个元素之外的所有子元素,并连接另一个分隔符和最后一个元素:

 int last = list.size() - 1; String joined = String.join(" and ", String.join(", ", list.subList(0, last)), list.get(last)); 

这是使用Collectors.collectingAndThen:执行上述操作的版本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)); }; } 

此版本还可以处理流为空或只有一个值的情况。 感谢Holger和Andreas提出的建议,这些建议大大改善了这一解决方案。

我在评论中建议牛津逗号可以使用", "", and"作为分隔符来完成,但这会产生两个元素的"a, and b"错误结果,所以只是为了好玩这里的一个牛津逗号正确:

 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)); }; } 

如果您对"a, b, and c" ,那么可以使用我的StreamEx库的mapLast方法,该方法使用其他操作扩展标准Stream API:

 String result = StreamEx.of("a", "b", "c") .mapLast("and "::concat) .joining(", "); // "a, b, and c" 

mapLast方法将给定映射应用于最后一个流元素,保持其他元素不变。 我甚至有类似的unit testing 。

尝试使用stream.collect(Collectors.joining(" and "))首先加入最后2个字符串

然后使用您在问题中使用的代码连接所有剩余的字符串和这个新字符串: stream.collect(Collectors.joining(", "))

如果您正在寻找旧的Java解决方案 ,那么使用Guava库会很容易。

  List values = Arrays.asList("a", "b", "c"); String output = Joiner.on(",").join(values); output = output.substring(0, output.lastIndexOf(","))+" and "+values.get(values.size()-1); System.out.println(output);//a,b and c 
  List names = Arrays.asList("Thomas", "Pierre", "Yussef", "Rick"); int length = names.size(); String result = IntStream.range(0, length - 1).mapToObj(i -> { if (i == length - 2) { return names.get(i) + " and " + names.get(length - 1); } else { return names.get(i); } }).collect(Collectors.joining(", ")); 
 String str = "a , b , c , d"; String what_you_want = str.substring(0, str.lastIndexOf(",")) + str.substring(str.lastIndexOf(",")).replace(",", "and"); // what_you_want is : a , b , c and d