2016-01-22 37 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(", ")); 
相关问题