连接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方法更整洁。
有任何想法/意见吗?
答案 0 :(得分:307)
使用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);
答案 1 :(得分:130)
使用Java 8 +
String str = list.stream().collect(Collectors.joining())
甚至
String str = String.join("", list);
答案 2 :(得分:44)
您的方法依赖于Java的ArrayList#toString()实现。
虽然Java API中记录了实现并且不太可能发生变化,但它有可能实现。自己实现它更可靠(循环,StringBuilders,递归,无论你更喜欢什么)。
当然,这种做法可能看起来“更整洁”或更“太甜蜜”或“金钱”,但在我看来,这是一种更糟糕的做法。
答案 3 :(得分:41)
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();
}
答案 4 :(得分:25)
如果您正在为Android开发,SDK会提供TextUtils.join
。
答案 5 :(得分:16)
这是我迄今为止发现的最优雅,最干净的方式:
list.stream().collect(Collectors.joining(delimiter));
答案 6 :(得分:15)
Guava是来自Google的非常简洁的图书馆:
Joiner joiner = Joiner.on(", ");
joiner.join(sList);
答案 7 :(得分:4)
您是否看过这篇Coding Horror博客文章?
The Sad Tragedy of Micro-Optimization Theater
不管它是否“整洁”,我并不感到害羞,但从表现的角度来看,它可能并不重要。
答案 8 :(得分:4)
我更喜欢Java 8中的String.join(list)
答案 9 :(得分:3)
如果你使用的是java 8,你可以编写一个单行代码,而不是依赖ArrayList.toString()
实现:
String result = sList.stream()
.reduce("", String::concat);
如果您希望使用StringBuffer
而不是字符串,因为String::concat
的运行时间为O(n^2)
,您可以先将String
转换为StringBuffer
。
StringBuffer result = sList.stream()
.map(StringBuffer::new)
.reduce(new StringBuffer(""), StringBuffer::append);
答案 10 :(得分:3)
在我看来,StringBuilder会快速有效。
基本形式看起来像这样:
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()方法。
答案 11 :(得分:3)
我以某种方式发现这比它更整洁 使用StringBuilder / StringBuffer 方法
我想这取决于你采取的方法。
AbstractCollection#toString()方法简单地遍历所有元素并将它们附加到StringBuilder。因此,您的方法可能会节省几行代码,但代价是额外的字符串操作。这种权衡是否是一个好的取决于你。
答案 12 :(得分:2)
假设移动指针/将字节设置为null(或者Java实现StringBuilder #setLength)更快,而不是每次通过循环检查条件以查看何时附加分隔符,您可以使用此方法:
public static String Intersperse (Collection<?> collection, String delimiter) { StringBuilder sb = new StringBuilder (); for (Object item : collection) { if (item == null) continue; sb.append (item).append (delimiter); } sb.setLength (sb.length () - delimiter.length ()); return sb.toString (); }
答案 13 :(得分:2)
Peter Lawrey的回答的下一个变化,没有在每次循环转换时初始化新字符串
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();
}
答案 14 :(得分:2)
ArrayList
从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(", ");
}
}
自己构建字符串会更有效率。
如果你真的想在某种List中预先聚合字符串,你应该提供自己的方法来有效地加入它们,例如:像这样:
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);
}
答案 15 :(得分:0)
使用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, ", ");
或者,通用方式,如果您没有字符串列表:
public static <A> String showList(List<A> l, Show<A> s) {
return stringMonoid.join(l.map(s.showS_()), ", ");
}
答案 16 :(得分:0)
如果你的依赖项中有json。你可以使用new JSONArray(list).toString()
答案 17 :(得分:0)
在java 8中,您还可以使用reducer,例如:
public static String join(List<String> strings, String joinStr) {
return strings.stream().reduce("", (prev, cur) -> prev += (cur + joinStr));
}
答案 18 :(得分:0)
根据性能需求和要添加的元素数量,这可能是一个不错的解决方案。如果元素数量很高,Arraylist
重新分配内存可能会比StringBuilder
慢一点。