4

我有一个字符串列表,例如星期几。我想用逗号加入他们,在最后一个元素之前加上“and”。例如:“我在周二、周三、周四周五有空”。

像优雅的东西

Joiner.on(", ").join(days)

不工作。有没有一种优雅的方式来使用 Guava 或类似的库?

谢谢

4

4 回答 4

4

没有直接的解决方案,但你可以考虑我的:

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() < 2if

于 2016-07-26T19:09:08.073 回答
3

考虑到您“此时对 Java 8 不友好”(您可能是指 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);
}

为了处理极端情况,我会选择Xaerxess switch solution

于 2016-07-26T21:40:07.063 回答
2

使用 Guava 的 Java 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);
    }
}

它处理除了 null 元素之外的所有边缘情况strings- 如果您想处理它们而不抛出 NPE,请添加.useForNull(stringForNull)到您的连接器。

于 2016-07-27T09:17:33.887 回答
1

感谢Java有replaceFirst但没有replaceLast,并假设“_,_”不会出现在任何元素/部分中,我破解了以下函数:

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

给:一,二,三和四

于 2016-07-26T19:50:09.340 回答