2016-01-22 39 views
7

使用stream.collect(Collectors.joining(", "))我可以輕鬆地加入由逗號分隔的所有字符串。可能的結果是"a, b, c"。但是如果我想讓最後一個分隔符有所不同,該怎麼辦?例如爲" and ",因此我得到"a, b and c"。有一個簡單的解決方案嗎?加入具有不同最後分隔符的字符串

+3

說實話 - 不,沒有。 'Collectors.joining'使用一些非常尷尬的技巧,當你嘗試這樣做時會完全崩潰。 –

+1

實現您自己的['Collector'](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector.html)。至於「輕鬆」,這是一個技巧和意見的問題。 – Andreas

+0

@Andreas是否有可能實現這樣一個收藏家?收集器如何知道何時使用特殊分隔符? –

回答

1

嘗試用stream.collect(Collectors.joining(" and "))

第一連結最後2串再加入所有剩餘的字符串,並與你在你的問題中使用的代碼這一新的字符串:stream.collect(Collectors.joining(", "))

4

如果它們已經在列表中,則不需要流;只需加入所有的子表,但最後一個元素和CONCAT其他分隔符和最後一個元素:

int last = list.size() - 1; 
String joined = String.join(" and ", 
        String.join(", ", list.subList(0, last)), 
        list.get(last)); 

這裏有一個版本,不使用Collectors.collectingAndThen:

stream.collect(Collectors.collectingAndThen(Collectors.toList(), 
    joiningLastDelimiter(", ", " and "))); 

public static Function<List<String>, String> joiningLastDelimiter(
     String delimiter, String lastDelimiter) { 
    return list -> { 
       int last = list.size() - 1; 
       if (last < 1) return String.join(delimiter, list); 
       return String.join(lastDelimiter, 
        String.join(delimiter, list.subList(0, last)), 
        list.get(last)); 
      }; 
} 

此版本還可以處理的情況下,上述流是空的或只有一個值。感謝Holger和Andreas的建議,這大大改進了這個解決方案。

我曾建議在的評價是牛津逗號可以用這種使用", "", and"作爲分隔符來完成,但產生的"a, and b"不正確的結果有兩個元素,所以只是爲了好玩這裏有一個正確呢牛津逗號:

stream.collect(Collectors.collectingAndThen(Collectors.toList(), 
    joiningOxfordComma())); 

public static Function<List<String>, String> joiningOxfordComma() { 
    return list -> { 
       int last = list.size() - 1; 
       if (last < 1) return String.join("", list); 
       if (last == 1) return String.join(" and ", list); 
       return String.join(", and ", 
        String.join(", ", list.subList(0, last)), 
        list.get(last)); 
      }; 
} 
+0

另外,我把它粘貼到Eclipse中,並得到一個編譯錯誤,可以通過明確給出類型來修復:'收集器。,String>(' – Andreas

+1

Hmm,'javac'不會給我一個編譯錯誤,但我可以添加顯式類型。什麼版本的Eclipse? –

+2

因爲這裏唯一相關的函數是* finisher *,你可以簡單地使用'Collectors.collectingAndThen(Collectors.toList(),list - > {...})'順便說一句,你也可以使用'String.join(lastDelimiter,String.join(delimiter,list.subList (0,last)),list.get(last))'返回語句 – Holger

-1
String str = "a , b , c , d"; 
String what_you_want = str.substring(0, str.lastIndexOf(",")) 
     + str.substring(str.lastIndexOf(",")).replace(",", "and"); 

// what_you_want is : a , b , c and d 
4

如果你罰款"a, b, and c",那麼就可以使用它擴展標準流API與額外的操作我StreamExmapLast方法:

String result = StreamEx.of("a", "b", "c") 
         .mapLast("and "::concat) 
         .joining(", "); // "a, b, and c" 

mapLast方法將給定的映射應用到最後一個流元素,以保持其他元素不變。我甚至有類似的unit-test

+0

這不是OP想要的答案,但是如果你是牛津逗號的粉絲,這個答案在語法上是「更」正確的。謝謝塔吉爾。 –

1

如果您正在尋找老的Java解決方案,使用Guava libraries會很容易。

List<String> values = Arrays.asList("a", "b", "c"); 
    String output = Joiner.on(",").join(values); 
    output = output.substring(0, output.lastIndexOf(","))+" and "+values.get(values.size()-1); 
    System.out.println(output);//a,b and c 
0
List<String> names = Arrays.asList("Thomas", "Pierre", "Yussef", "Rick"); 
    int length = names.size(); 
    String result = IntStream.range(0, length - 1).mapToObj(i -> { 
     if (i == length - 2) { 
      return names.get(i) + " and " + names.get(length - 1); 
     } else { 
      return names.get(i); 
     } 
    }).collect(Collectors.joining(", ")); 
相關問題