连接string对象列表的最佳方法是什么?

串联一个String对象列表的最佳方法是什么? 我正在考虑这样做:

List<String> sList = new ArrayList<String>(); // add elements if (sList != null) { String listString = sList.toString(); listString = listString.subString(1, listString.length() - 1); } 

我不知何故发现这比使用StringBuilder / StringBuffer方法更整齐。

任何想法/意见?

你的方法依赖于Java的ArrayList#toString()实现。

虽然这个实现在Java API中有logging,而且不太可能改变,但它有可能。 自己实现这个要可靠得多(循环,StringBuilders,recursion,无论你喜欢什么)。

当然,这种做法可能看起来是“整洁的”,也可能是“太甜”或“金钱”,但在我看来,这是一种糟糕的做法。

使用Apache Commons Lang中的一个StringUtils.join方法。

 import org.apache.commons.lang3.StringUtils; String result = StringUtils.join(list, ", "); 

如果你有幸使用Java 8,那么更简单一点就是使用String.join

 String result = String.join(", ", list); 

使用Java 8+

 String str = list.stream().collect(Collectors.joining()) 

甚至

 String str = String.join("", list); 

codefin的答案变化

 public static String concatStringsWSep(Iterable<String> strings, String separator) { StringBuilder sb = new StringBuilder(); String sep = ""; for(String s: strings) { sb.append(sep).append(s); sep = separator; } return sb.toString(); } 

如果您正在为Android开发,那么SDK提供了TextUtils.join

番石榴是来自Google的漂亮图书馆:

 Joiner joiner = Joiner.on(", "); joiner.join(sList); 

这是迄今为止我发现的最优雅和最干净的方式:

 list.stream().collect(Collectors.joining(delimiter)); 

你看过这个Coding Horror博客条目吗?

微型优化剧院的悲剧悲剧

我不确定它是否“整洁”,但从性能的angular度来看,这可能并不重要。

我更喜欢Java 8中的String.join(list)

如果你正在使用java 8,你可以写一个单行的,而不是依赖于ArrayList.toString()实现:

 String result = sList.stream() .reduce("", String::concat); 

如果您更喜欢使用StringBuffer而不是String,因为String::concat的运行时间为O(n^2) ,您可以先将每个String转换为StringBuffer

 StringBuffer result = sList.stream() .map(StringBuffer::new) .reduce(new StringBuffer(""), StringBuffer::append); 

我不知何故发现这比使用StringBuilder / StringBuffer方法更整齐。

我想这取决于你采取了什么方法。

AbstractCollection#toString()方法只遍历所有元素,并将它们附加到StringBuilder。 所以你的方法可能会节省几行代码,但代价是额外的string操作。 这种权衡是否合理取决于你。

在我看来,StringBuilder将是快速和高效的。

基本forms看起来像这样:

 public static String concatStrings(List<String> strings) { StringBuilder sb = new StringBuilder(); for(String s: strings) { sb.append(s); } return sb.toString(); } 

如果这太简单了(可能是这样),你可以使用类似的方法,像这样添加一个分隔符:

  public static String concatStringsWSep(List<String> strings, String separator) { StringBuilder sb = new StringBuilder(); for(int i = 0; i < strings.size(); i++) { sb.append(strings.get(i)); if(i < strings.size() - 1) sb.append(separator); } return sb.toString(); } 

我同意那些回答这个问题的人,他们说你不应该依赖Java的ArrayList的toString()方法。

假设只是移动一个指针/设置一个字节为空(或者Java实现StringBuilder#setLength)会更快,而不是每次通过循环检查一个条件以查看何时附加分隔符,那么可以使用以下方法:

  public static String Intersperse(Collection <?> collection,String delimiter)
 {
     StringBuilder sb = new StringBuilder();
     for(对象项目:集合)
     {
        如果(item == null)继续;
         sb.append(item).append(delimiter);
     }
     sb.setLength(sb.length() -  delimiter.length());
    返回sb.toString();
 } 

Peter Lawrey的答案的下一个变化,没有在每个循环中初始化一个新的string

 String concatList(List<String> sList, String separator) { Iterator<String> iter = sList.iterator(); StringBuilder sb = new StringBuilder(); while (iter.hasNext()) { sb.append(iter.next()).append( iter.hasNext() ? separator : ""); } return sb.toString(); } 

ArrayListinheritance自AbstractCollection toString() – 方法,即:

 public String toString() { Iterator<E> i = iterator(); if (! i.hasNext()) return "[]"; StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { E e = i.next(); sb.append(e == this ? "(this Collection)" : e); if (! i.hasNext()) return sb.append(']').toString(); sb.append(", "); } } 

build立自己的string会更有效率。


如果你真的想在某种列表中预先聚合string,你应该提供自己的方法来有效地join它们,例如:

 static String join(Collection<?> items, String sep) { if(items.size() == 0) return ""; String[] strings = new String[items.size()]; int length = sep.length() * (items.size() - 1); int idx = 0; for(Object item : items) { String str = item.toString(); strings[idx++] = str; length += str.length(); } char[] chars = new char[length]; int pos = 0; for(String str : strings) { str.getChars(0, str.length(), chars, pos); pos += str.length(); if(pos < length) { sep.getChars(0, sep.length(), chars, pos); pos += sep.length(); } } return new String(chars); } 

在Java 8中,你也可以使用reducer,如下所示:

 public static String join(List<String> strings, String joinStr) { return strings.stream().reduce("", (prev, cur) -> prev += (cur + joinStr)); } 

根据性能需求和要添加的元素数量,这可能是一个好的解决scheme。 如果元素的数量很高, Arraylist的内存重新分配可能比StringBuilder慢一点。

使用Functional Java库,导入这些:

 import static fj.pre.Monoid.stringMonoid; import static fj.data.List.list; import fj.data.List; 

…那么你可以这样做:

 List<String> ss = list("foo", "bar", "baz"); String s = stringMonoid.join(ss, ", "); 

或者,通用的方法,如果你没有一个string列表:

 public static <A> String showList(List<A> l, Show<A> s) { return stringMonoid.join(l.map(s.showS_()), ", "); } 

如果你有你的依赖json。你可以使用new JSONArray(list).toString()