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

pri*_*ain 8 java string java-8 java-stream

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

Dav*_*rad 7

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

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

这是一个使用上述功能的版本 Collectors.collectingAndThen:

stream.collect(Collectors.collectingAndThen(Collectors.toList(),
    joiningLastDelimiter(", ", " and ")));

public static Function<List<String>, 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));
            };
}
Run Code Online (Sandbox Code Playgroud)

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

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

stream.collect(Collectors.collectingAndThen(Collectors.toList(),
    joiningOxfordComma()));

public static Function<List<String>, 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));
            };
}
Run Code Online (Sandbox Code Playgroud)

  • 由于这里唯一相关的功能是*终结者*,你可以简单地使用`Collectors.collectingAndThen(Collectors.toList(),list - > {...})`.顺便说一下,你也可以使用`String.join(lastDelimiter,String.join(delimiter,list.subList(0,last)),list.get(last))`作为return语句. (2认同)

Tag*_*eev 5

如果您对没问题"a, b, and c",则可以使用mapLast我的StreamEx库的方法,该方法通过其他操作扩展了标准Stream API:

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

mapLast方法将给定的映射应用于最后一个流元素,使其他元素保持不变。我什至也有类似的单元测试