在 Java 中连接具有不同分隔符的字符串
Join strings with different separators in Java
我有一个字符串列表,例如一周中的日子。我想用逗号加入它们,在最后一个元素之前加上 "and"。例如:"I'm available on Tue, Wed, Thu and Fri".
像
这样优雅的东西
Joiner.on(", ").join(days)
无效。有没有一种优雅的方法可以使用 Guava 或类似的库来做到这一点?
谢谢
没有直接的解决方案,但您可以考虑我的:
final String COMMA = ", ", AND = " and ";
List<String> list = Arrays.asList("Tue", "Wed", "Thu", "Fri");
int last = list.size() - 1;
Joiner.on(AND).join(
list.stream().limit(last).collect(joining(COMMA)),
list.get(last)); // Tue, Wed, Thu and Fri
另一种较短的方式是:
list.stream().limit(last).collect(joining(COMMA, "", AND))
.concat(list.get(last));
这些方法完美地工作了 2 天以上。
边缘情况(list == null || list.isEmpty()
和 list.size() < 2
)可以由 if
语句处理。
感谢 Java 有 replaceFirst 但没有 replaceLast,并且假设“_,_”不会出现在任何 elements/parts 中,我破解了以下函数:
public static String join(Iterable<?> parts) {
String reverse = new StringBuilder(Joiner.on("_,_").join(parts)).reverse().toString();
reverse = reverse.replaceFirst("_,_", " dna ").replaceAll("_,_", " ,");
return new StringBuilder(reverse).reverse().toString();
}
然后:
System.out.println(join(Arrays.asList("One", "Two", "Three", "Four")));
给出:
一、二、三、四
考虑到您是 "not Java 8 friendly at this moment"(您可能指的是 lambda 和流),使用 StringJoiner
怎么样:
public static String join(List<String> parts, String delimiter, String lastDelimiter) {
StringJoiner joiner = new StringJoiner(delimiter, "", lastDelimiter);
for (int i = 0; i < parts.size() - 1; i++) {
joiner.add(parts.get(i));
}
return joiner.toString() + parts.get(parts.size() - 1);
}
然而,对流做同样的事情:
public static String join(List<String> parts, String delimiter, String lastDelimiter) {
return parts.stream()
.limit(parts.size() - 1)
.collect(Collectors.joining(delimiter, "", lastDelimiter))
.concat(parts.get(parts.size() - 1));
}
编辑: 刚找到 String#join(CharSequence, Iterable<? extends CharSequence>)
:
public static String join(List<String> parts, String delimiter, String lastDelimiter) {
return String.join(delimiter, parts.subList(0, parts.size() - 1))
+ lastDelimiter + parts.get(parts.size() - 1);
}
为了处理极端情况,我会选择 。
Java 使用 Guava 的 6/7 兼容解决方案:
static String join(List<String> strings, String separator, String lastSeparator)
{
checkNotNull(strings);
switch (strings.size()) {
case 0:
return "";
case 1:
return strings.get(0);
default:
return Joiner.on(separator).join(strings.subList(0, strings.size() - 1))
+ lastSeparator + strings.get(strings.size() - 1);
}
}
或者如果你想接受 Iterable
(和/或使用更多番石榴的东西):
static String join(Iterable<String> strings, String separator, String lastSeparator)
{
checkNotNull(strings);
int size = Iterables.size(strings);
switch (size) {
case 0:
return "";
case 1:
return strings.iterator().next();
default:
return Joiner.on(separator).join(Iterables.limit(strings, size - 1))
+ lastSeparator + Iterables.getLast(strings);
}
}
它处理除 strings
中的空元素之外的所有边缘情况 - 如果您想处理它们而不抛出 NPE,请将 .useForNull(stringForNull)
添加到您的连接器中。
我有一个字符串列表,例如一周中的日子。我想用逗号加入它们,在最后一个元素之前加上 "and"。例如:"I'm available on Tue, Wed, Thu and Fri".
像
这样优雅的东西Joiner.on(", ").join(days)
无效。有没有一种优雅的方法可以使用 Guava 或类似的库来做到这一点?
谢谢
没有直接的解决方案,但您可以考虑我的:
final String COMMA = ", ", AND = " and ";
List<String> list = Arrays.asList("Tue", "Wed", "Thu", "Fri");
int last = list.size() - 1;
Joiner.on(AND).join(
list.stream().limit(last).collect(joining(COMMA)),
list.get(last)); // Tue, Wed, Thu and Fri
另一种较短的方式是:
list.stream().limit(last).collect(joining(COMMA, "", AND))
.concat(list.get(last));
这些方法完美地工作了 2 天以上。
边缘情况(list == null || list.isEmpty()
和 list.size() < 2
)可以由 if
语句处理。
感谢 Java 有 replaceFirst 但没有 replaceLast,并且假设“_,_”不会出现在任何 elements/parts 中,我破解了以下函数:
public static String join(Iterable<?> parts) {
String reverse = new StringBuilder(Joiner.on("_,_").join(parts)).reverse().toString();
reverse = reverse.replaceFirst("_,_", " dna ").replaceAll("_,_", " ,");
return new StringBuilder(reverse).reverse().toString();
}
然后:
System.out.println(join(Arrays.asList("One", "Two", "Three", "Four")));
给出: 一、二、三、四
考虑到您是 "not Java 8 friendly at this moment"(您可能指的是 lambda 和流),使用 StringJoiner
怎么样:
public static String join(List<String> parts, String delimiter, String lastDelimiter) {
StringJoiner joiner = new StringJoiner(delimiter, "", lastDelimiter);
for (int i = 0; i < parts.size() - 1; i++) {
joiner.add(parts.get(i));
}
return joiner.toString() + parts.get(parts.size() - 1);
}
然而,对流做同样的事情:
public static String join(List<String> parts, String delimiter, String lastDelimiter) {
return parts.stream()
.limit(parts.size() - 1)
.collect(Collectors.joining(delimiter, "", lastDelimiter))
.concat(parts.get(parts.size() - 1));
}
编辑: 刚找到 String#join(CharSequence, Iterable<? extends CharSequence>)
:
public static String join(List<String> parts, String delimiter, String lastDelimiter) {
return String.join(delimiter, parts.subList(0, parts.size() - 1))
+ lastDelimiter + parts.get(parts.size() - 1);
}
为了处理极端情况,我会选择
Java 使用 Guava 的 6/7 兼容解决方案:
static String join(List<String> strings, String separator, String lastSeparator)
{
checkNotNull(strings);
switch (strings.size()) {
case 0:
return "";
case 1:
return strings.get(0);
default:
return Joiner.on(separator).join(strings.subList(0, strings.size() - 1))
+ lastSeparator + strings.get(strings.size() - 1);
}
}
或者如果你想接受 Iterable
(和/或使用更多番石榴的东西):
static String join(Iterable<String> strings, String separator, String lastSeparator)
{
checkNotNull(strings);
int size = Iterables.size(strings);
switch (size) {
case 0:
return "";
case 1:
return strings.iterator().next();
default:
return Joiner.on(separator).join(Iterables.limit(strings, size - 1))
+ lastSeparator + Iterables.getLast(strings);
}
}
它处理除 strings
中的空元素之外的所有边缘情况 - 如果您想处理它们而不抛出 NPE,请将 .useForNull(stringForNull)
添加到您的连接器中。