2016-07-26 31 views
3

我有一个字符串列表,例如一周中的日子。我想用逗号加入他们,在最后一个元素之前加上“和”。例如:“我可以在星期二,星期三,星期四星期五”。在Java中使用不同分隔符的字符串

高雅的东西像

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

不工作。有没有一种用番石榴或类似的图书馆做的优雅方式?

感谢

+2

获取从上面的语句的结果,就劈在最后一个分隔符,用任何你想要的追加。我不认为有任何预定义的方法可用于您正在寻找的。 – kosa

+0

这是一个很好的解决方案,但如果我不使用日期,则可能不正确。如果我使它成为通用函数,并且加入的元素具有分隔符,那么我遇到了麻烦...... –

+0

如果您想要使用泛型函数,那么不要在连接条件中追加最后一个元素(将该元素从列表中移出你正在通过加入)并编写自己的方法来追加最后一个,这将足够通用以处理任何情况。你可以通过创建一个带有索引的单一方法来分隔第一组元素和第二组元素,以及用户定义的联接“文本”,从而使其更具通用性。使用两个连接并追加两个连接的结果。 – kosa

回答

2

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

它可以处理所有的特殊情况除外在strings null元素 - 如果你要处理他们,而不是抛出NPE,添加.useForNull(stringForNull)到您的木匠。

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() < 2)可能由if语句处理。

+0

谢谢,没关系,列表或数组,这是我正在考虑的方向... –

+0

P.S.令人讨厌的是我必须照顾边缘情况。例如。你的代码会在空列表上抛出异常。这不是很多工作,但我希望Guava有一个单线解决方案.. –

+0

Ush,忘了提及我现在不是Java 8友好的...... –

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

给出: 一,二,三,四

+0

你可以使用'replaceFirst(“((? s:。*)_,_“,”$ 1 and“)'。 – maaartinus

2

考虑你“不是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); 
} 

为了应付极端情况我'd去Xaerxess switch solution

+0

不幸的是,'StringJoiner'也只适用于Java 8+。 – Xaerxess

+0

@Xaerxess:我知道,这就是为什么我说”你可能是指lambda表达式和流“我认为(并且仍然认为)OP正在谈论他们随附的不同语法/编码风格,当然,如果他不想(或不能)使用JDK 8,那不是有效的方案。 – beatngu13