用Java加入字符串集合的首选成语

Preferred Idiom for Joining a Collection of Strings in Java

给定一个字符串集合,在没有使用外部库的情况下,如何将它们加入到普通Java中?

考虑到这些变量:

1
2
3
Collection<String> data = Arrays.asList("Snap","Crackle","Pop");
String separator =",";
String joined; // let's create this, shall we?

这就是我在番石榴的方式:

1
joined = Joiner.on(separator).join(data);

在Apache Commons/lang中:

1
joined = StringUtils.join(data, separator);

但在普通Java中,真的没有比这更好的方法吗?

1
2
3
4
5
6
StringBuilder sb = new StringBuilder();
for(String item : data){
    if(sb.length()>0)sb.append(separator);
    sb.append(item);
}
joined = sb.toString();


我想说,最好的方法是在不使用番石榴的情况下使用番石榴内部使用的技术(最好你不是指"最简洁"),在你的例子中,这种方法看起来像这样:

1
2
3
4
5
6
7
8
9
Iterator<String> iter = data.iterator();
StringBuilder sb = new StringBuilder();
if (iter.hasNext()) {
  sb.append(iter.next());
  while (iter.hasNext()) {
    sb.append(separator).append(iter.next());
  }
}
String joined = sb.toString();

这不需要在迭代时进行布尔检查,也不需要对字符串进行任何后处理。


可能不是在循环中一次又一次地调用sb.length(),我做了一些修改。

1
2
3
4
5
6
7
8
StringBuilder sb = new StringBuilder();
String separator ="";
for(String item : data){
    sb.append(separator);
    separator=",";
    sb.append(item);
}
joined = sb.toString();


Java 8 +

joined =String.join(separator, data);

Java 7及以下

1
2
3
4
5
6
7
StringBuilder sb = new StringBuilder();
boolean first = true;
for(String item : data){
    if(!first || (first = false)) sb.append(separator);
    sb.append(item);
}
joined = sb.toString();


在Java 8中:

1
String.join (separator, data)

收集器可以加入流,如果您希望filtermap您的数据,这非常有用。

1
2
3
String joined = Stream.of("Snap","Crackle","Pop")
        .map(String::toUpperCase)
        .collect(Collectors.joining(","));

要从集合中获取流,请在集合上调用stream()

1
Arrays.asList("Snap","Crackle","Pop").stream()

不同的意图:

对于第三部分的工具,如guava的Joiner,它不是很快,但非常灵活。有许多自定义连接行为的选项方法,例如skipNulls()

普通Java是快速的,但它需要你自己编写一些代码。


你的建议是一个可能的解决方案,另一个常见的建议是:

1
2
3
4
5
for (String item: data) {
    sb.append(item)
    sb.append(separator);
}
String joined = sb.substring(0, sb.length() - separator.length())