Java 连接字符串对象列表的最佳方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/523871/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to concatenate List of String objects?
提问by Jagmal
What is the best way to concatenate a list of String objects? I am thinking of doing this way:
连接 String 对象列表的最佳方法是什么?我正在考虑这样做:
List<String> sList = new ArrayList<String>();
// add elements
if (sList != null)
{
String listString = sList.toString();
listString = listString.subString(1, listString.length() - 1);
}
I somehow found this to be neater than using the StringBuilder/StringBuffer approach.
我以某种方式发现这比使用 StringBuilder/StringBuffer 方法更简洁。
Any thoughts/comments?
任何想法/意见?
采纳答案by Hyman Leow
Your approach is dependent on Java's ArrayList#toString() implementation.
您的方法取决于 Java 的 ArrayList#toString() 实现。
While the implementation is documented in the Java API and very unlikely to change, there's a chance it could. It's far more reliable to implement this yourself (loops, StringBuilders, recursion whatever you like better).
虽然实现记录在 Java API 中并且不太可能改变,但有可能会改变。自己实现它(循环,StringBuilders,递归,无论你喜欢什么)都要可靠得多。
Sure this approach may seem "neater" or more "too sweet" or "money" but it is, in my opinion, a worse approach.
当然,这种方法可能看起来“更整洁”或更“太甜”或“金钱”,但在我看来,这是一种更糟糕的方法。
回答by Kevin
I somehow found this to be neater than using the StringBuilder/StringBuffer approach.
我以某种方式发现这比使用 StringBuilder/StringBuffer 方法更简洁。
I guess it depends on what approach you took.
我想这取决于你采取的方法。
The AbstractCollection#toString() method simply iterates over all the elements and appends them to a StringBuilder. So your method may be saving a few lines of code but at the cost of extra String manipulation. Whether that tradeoff is a good one is up to you.
AbstractCollection#toString() 方法简单地遍历所有元素并将它们附加到 StringBuilder。所以你的方法可能会节省几行代码,但代价是额外的字符串操作。这种权衡是否良好取决于您。
回答by georg
Depending on the need for performance and amount of elements to be added, this might be an ok solution. If the amount of elements are high, the Arraylist
s reallocation of memory might be a bit slower than StringBuilder
.
根据性能需求和要添加的元素数量,这可能是一个不错的解决方案。如果元素数量较多,则Arraylist
内存的重新分配可能会比 慢一点StringBuilder
。
回答by Christoph
ArrayList
inherits its toString()
-method from AbstractCollection
, ie:
ArrayList
从 继承其toString()
-method AbstractCollection
,即:
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(", ");
}
}
Building the string yourself will be far more efficient.
自己构建字符串会更有效率。
If you really want to aggregate the strings beforehand in some sort of List, you should provide your own method to efficiently join them, e.g. like this:
如果你真的想预先在某种列表中聚合字符串,你应该提供你自己的方法来有效地连接它们,例如:
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);
}
回答by sdfx
Have you seen this Coding Horror blog entry?
你看过这个 Coding Horror 博客吗?
The Sad Tragedy of Micro-Optimization Theater
I am not shure whether or not it is "neater", but from a performance-standpoint it probably won't matter much.
我不确定它是否“更整洁”,但从性能的角度来看,它可能无关紧要。
回答by codefin
It seems to me that the StringBuilder will be quick and efficient.
在我看来,StringBuilder 将快速高效。
The basic form would look something like this:
基本形式如下所示:
public static String concatStrings(List<String> strings)
{
StringBuilder sb = new StringBuilder();
for(String s: strings)
{
sb.append(s);
}
return sb.toString();
}
If that's too simplistic (and it probably is), you can use a similar approach and add a separator like this:
如果这太简单了(可能确实如此),您可以使用类似的方法并添加这样的分隔符:
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();
}
I agree with the others who have responded to this question when they say that you should not rely on the toString() method of Java's ArrayList.
我同意其他回答这个问题的人说你不应该依赖 Java ArrayList 的 toString() 方法。
回答by Peter Lawrey
A variation on codefin's answer
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();
}
回答by Jeff Olson
Use one of the the StringUtils.joinmethods in Apache Commons Lang.
使用Apache Commons Lang 中的StringUtils.join方法之一。
import org.apache.commons.lang3.StringUtils;
String result = StringUtils.join(list, ", ");
If you are fortunate enough to be using Java 8, then it's even easier...just use String.join
如果您有幸使用 Java 8,那么它会更简单……只需使用String.join
String result = String.join(", ", list);
回答by Apocalisp
Using the Functional Javalibrary, import these:
使用Functional Java库,导入这些:
import static fj.pre.Monoid.stringMonoid;
import static fj.data.List.list;
import fj.data.List;
... then you can do this:
...然后你可以这样做:
List<String> ss = list("foo", "bar", "baz");
String s = stringMonoid.join(ss, ", ");
Or, the generic way, if you don't have a list of Strings:
或者,通用方式,如果您没有字符串列表:
public static <A> String showList(List<A> l, Show<A> s) {
return stringMonoid.join(l.map(s.showS_()), ", ");
}
回答by Apocalisp
Assuming it's faster to just move a pointer / set a byte to null (or however Java implements StringBuilder#setLength), rather than check a condition each time through the loop to see when to append the delimiter, you could use this method:
假设仅移动指针/将字节设置为 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 (); }