2016-07-26 71 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