2011-11-24 46 views
26

給出一個列表加入列表<String>在Java中使用逗號和 「和」

List<String> l = new ArrayList<String>(); 
l.add("one"); 
l.add("two"); 
l.add("three"); 

我有一個方法

String join(List<String> messages) { 
     if (messages.isEmpty()) return ""; 
     if (messages.size() == 1) return messages.get(0); 
     String message = ""; 
     message = StringUtils.join(messages.subList(0, messages.size() -2), ", "); 
     message = message + (messages.size() > 2 ? ", " : "") + StringUtils.join(messages.subList(messages.size() -2, messages.size()), ", and "); 
     return message; 
    } 

其中,對於L,生產的 「一,二,三」 。 我的問題是,是否有,做同樣的?,例如

WhatEverUtils.join(l, ", ", ", and "); 

爲了闡明標準(Apache的公地)方法。我的問題是沒有得到這種方法的工作。它的工作方式與我想要的一樣,經過測試,一切正常。我的問題是,我找不到一些實現這種功能的apache-commons-like模塊。這讓我感到驚訝,因爲我不能成爲第一個需要這個的人。

但隨後也許其他人剛剛做

StringUtils.join(l, ", ").replaceAll(lastCommaRegex, ", and"); 
+0

我不認爲有這樣一個開源庫,但我建議使用資源包,因爲不是所有的語言都使用英文單詞「和」。 –

+0

@slipset,爲什麼不使用來自已知庫的一些連接,只需修改一下?注意「和」是英文單詞,所以如果這樣的庫存在,它必須有多種語言支持 – smas

+0

我可能一直不清楚,但是我寫了我在我的問題中顯示的方法,並且它的工作方式與我想要的一樣。 – slipset

回答

13

我喜歡使用谷歌收集用於這一目的。乾淨,也非常有用:

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

這種代碼已被再次寫入時間和時間,你應該而被釋放,實現您的具體實現邏輯。

如果您使用的是Maven,特此依賴:

<dependency> 
    <groupId>com.google.collections</groupId> 
    <artifactId>google-collections</artifactId> 
    <version>1.0</version> 
</dependency> 

它還包含了許多其他精彩的酷功能呢!

編輯:爲了完整起見,這將產生列表「一,二,三」。

List<String> originalList = Arrays.asList("one", "two", "three"); 
Joiner.on(", ").join(originalList.subList(0, originalList.size() - 1)) 
    .concat(", and ").concat(originalList.get(originalList.size() - 1)); 
+2

只是FYI:谷歌集合已被棄用,支持Guava(http://code.google.com/p/guava-libraries/)這是一個完全向後兼容的超集。 –

+0

非常正確..我忘了這一點。 Maven的依賴關係,如果有人有興趣: com.google.guava 番石榴 10.0.1

+1

我不明白爲什麼你downvoting的答案加入的生產方法:「一, 二三」。用你想要的任何字符串替換最後一個逗號是非常困難的,或者類似的東西?!這是100%好的答案,它給了@slipset可以解決他的問題的可能方向。 – smas

1

我不知道任何Apache字符串連接器可以支持在連接字符串中添加and

下面是一個未經測試的代碼,會做什麼你問:

public static String join(String separator, List<String> mList, boolean includeAndInText) { 
    StringBuilder sb = new StringBuilder(); 
    int count = 0; 

    for (String m: mList) { 
     if (includeAndInText && (count + 1 != mList.size())) { 
      sb.append (" and "); 
     } 

     sb.append(m); 
     count++; 
     if (count < mList.size()) { 
      sp.append(separator); 
     }  
    } 

    return sb.toString(); 
} 
+0

對不起,但我不認爲這是解決此問題的最佳方法。海事組織我們應該使用存在的東西(例如,從Apache加入)並修改它以獲得「和」,「或」或我們期望的東西。 – smas

+0

@smas,好吧,我不同意。改變一個現有的庫以符合你的** only **要求並不是一個明顯的選擇,因爲(而且我不相信)你會將改變提交給Apache。另外,如果另一個版本的'StringUtils'被釋放,你將不得不維護它並確保你的改變不受影響(刪除)。我說,離開圖書館實施AS-IS並編寫你自己的Utility類。 –

+1

我也是diagree。在商業世界中,像StringUtils這樣的着名庫很常用,以避免重新發明輪子。如果你知道一些變化,你可以編寫單元測試。對於這種情況,只能自己寫連接,因爲「和」必須是浪費時間,金錢和麪向對象的編程風格。 – smas

11

什麼約joinorg.apache.commons.lang.StringUtils

例子:

StringUtils.join(new String[] { "one", "two", "three" }, ", "); // one, two, three 

有 「和」 或」和「你可以簡單地替換最後的逗號。

+0

根據OP要求,不會產生「一,二,三」。注意:他在他的問題 –

+0

@Lukas中使用了「加入」方法,但是您可以替換最後一個逗號,對不對?我沒有看到有感覺有這個「和」加入方法爲我添加的庫。 – smas

+0

僅供參考 - 我已經提出https://issues.apache.org/jira/browse/LANG-1037請求包含其他方法來執行此操作。我會嘗試在下一個版本中實現它。 –

3

其他答案討論「替換最後的逗號」,如果最後一個詞本身包含逗號,這是不安全的。

而不是使用一個庫,你可以使用JDK一個代碼(雖然長)線:

public static String join(List<String> msgs) { 
    return msgs == null || msgs.size() == 0 ? "" : msgs.size() == 1 ? msgs.get(0) : msgs.subList(0, msgs.size() - 1).toString().replaceAll("^.|.$", "") + " and " + msgs.get(msgs.size() - 1); 
} 

看到這個代碼處理所有的特殊情況的live demo


僅供參考,這裏有一個更可讀的兩班輪:

public static String join(List<String> msgs) { 
    int size = msgs == null ? 0 : msgs.size(); 
    return size == 0 ? "" : size == 1 ? msgs.get(0) : msgs.subList(0, --size).toString().replaceAll("^.|.$", "") + " and " + msgs.get(size); 
} 
7

與Java 8中,您可以使用流與加入者。

Collection<String> strings; 
... 
String commaDelimited = strings.stream().collect(Collectors.joining(",")); 
// use strings.parallelStream() instead, if you think 
// there are gains to be had by doing fork/join 
21

在Java 8,您可以使用String.join()像以下:

Collection<String> elements = ....; 
String result = String.join(", ", elements); 
0

以英語產生語法輸出有3種情況連接字符串列表時要考慮:

  1. 「A」

  2. 「A和B」

  3. 「A,B,和C.

這可以通過使用標準的Java或番石榴像下面來完成。解決方案基本相同,只是您喜歡使用什麼。

import com.google.common.base.Joiner; 
import com.google.common.collect.ImmutableList; 

import org.junit.Test; 

import java.util.List; 

import static org.junit.Assert.assertEquals; 

public class JoinListTest { 

    @Test 
    public void test_join() { 
     // create cases (don't need to use ImmutableList builder from guava) 
     final List<String> case1 = new ImmutableList.Builder<String>().add("A").build(); 
     final List<String> case2 = new ImmutableList.Builder<String>().add("A", "B").build(); 
     final List<String> case3 = new ImmutableList.Builder<String>().add("A", "B", "C").build(); 
     // test with standard java 
     assertEquals("A", joinListGrammaticallyWithJava(case1)); 
     assertEquals("A and B", joinListGrammaticallyWithJava(case2)); 
     assertEquals("A, B, and C", joinListGrammaticallyWithJava(case3)); 
     // test with guava 
     assertEquals("A", joinListGrammaticallyWithGuava(case1)); 
     assertEquals("A and B", joinListGrammaticallyWithGuava(case2)); 
     assertEquals("A, B, and C", joinListGrammaticallyWithGuava(case3)); 
    } 

    private String joinListGrammaticallyWithJava(final List<String> list) { 
     return list.size() > 1 
       ? String.join(", ", list.subList(0, list.size() - 1)) 
        .concat(String.format("%s and ", list.size() > 2 ? "," : "")) 
        .concat(list.get(list.size() - 1)) 
       : list.get(0); 
    } 

    private String joinListGrammaticallyWithGuava(final List<String> list) { 
     return list.size() > 1 
       ? Joiner.on(", ").join(list.subList(0, list.size() - 1)) 
        .concat(String.format("%s and ", list.size() > 2 ? "," : "")) 
        .concat(list.get(list.size() - 1)) 
       : list.get(0); 
    } 

} 
相關問題