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

Jag*_*mal 141 java string list

连接String对象列表的最佳方法是什么?我想这样做:

List<String> sList = new ArrayList<String>();

// add elements

if (sList != null)
{
    String listString = sList.toString();
    listString = listString.subString(1, listString.length() - 1);
}
Run Code Online (Sandbox Code Playgroud)

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

有什么想法/意见吗?

Jef*_*son 320

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

import org.apache.commons.lang3.StringUtils;

String result = StringUtils.join(list, ", ");
Run Code Online (Sandbox Code Playgroud)

如果你有幸使用Java 8,那么它就更容易了......只需使用String.join

String result = String.join(", ", list);
Run Code Online (Sandbox Code Playgroud)

  • 是的,每一次:Bloch,"Effective Java",第47项:"了解并使用库".Apache Commons库应该是第一个放入构建文件的东西(希望是Gradle).正如第47项所述:"总而言之,不要重新发明轮子". (2认同)
  • 使用Guava API:`Joiner.on(',').skipNulls().join(Iterable <?>)`.要表示空值,可以使用`Joiner.on(',').useForNull("#").join(Iterable <?>)` (2认同)
  • 从 Java 8 开始,最好使用 String#join(不需要库)。 (2认同)

And*_*i N 146

使用Java 8+

String str = list.stream().collect(Collectors.joining())
Run Code Online (Sandbox Code Playgroud)

甚至

String str = String.join("", list);
Run Code Online (Sandbox Code Playgroud)


Jac*_*eow 45

您的方法依赖于Java的ArrayList#toString()实现.

虽然Java API中记录了实现并且不太可能发生变化,但它有可能实现.自己实现它更可靠(循环,StringBuilders,递归,无论你更喜欢什么).

当然,这种方法可能看起来"更整洁"或更"太甜"或"钱",但在我看来,这是一种更糟糕的方法.

  • 我同意我不喜欢OP的做法,但出于不同的原因.(1)这样做可以伪装代码的意图(而像StringUtils.join`这样的东西是完全可读的).(2)它不灵活,因为您可能想要更改分隔符.(只是替换`","在最后一个字符串中``不是一个好方法,因为可能有``,'`嵌入在原始字符串中.)所以即使如你所说,`ArrayList.toString`可能赢了不会改变,我仍然不会走这条路. (8认同)
  • 您可以99.9%确定ArrayList.toString不会改变,除非它以某种方式成为攻击向量; 向后兼容性将会看到.但我同意使用toString()仍然是一个坏主意. (4认同)

Pet*_*rey 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();                           
}
Run Code Online (Sandbox Code Playgroud)


Chu*_*Lyu 27

如果您正在为Android开发,TextUtils.join则由SDK提供.


Ale*_*vic 18

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

list.stream().collect(Collectors.joining(delimiter));
Run Code Online (Sandbox Code Playgroud)

  • IntelliJ给我一个提示,我可以通过将其他答案更改为String.join示例的解决方案来改善事情,其理由如下:“报告流API调用链可以简化。它避免遍历集合时创建多余的临时对象”。 (2认同)

and*_*ras 16

Guava是来自Google的一个非常简洁的图书馆:

Joiner joiner = Joiner.on(", ");
joiner.join(sList);
Run Code Online (Sandbox Code Playgroud)


Man*_*ani 6

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


Chr*_*oph 5

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(", ");
    }
}
Run Code Online (Sandbox Code Playgroud)

自己构建字符串会更有效率。


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

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);
}
Run Code Online (Sandbox Code Playgroud)


sdf*_*dfx 5

您是否看到过此Coding Horror博客条目?

微观优化剧院的悲剧

我不确定它是否“更整洁”,但是从性能的角度来看,这可能无关紧要。


小智 5

在我看来,StringBuilder将快速有效。

基本形式如下所示:

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

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

    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();               
}
Run Code Online (Sandbox Code Playgroud)

我同意回答这个问题的其他人所说的,您不应依赖Java ArrayList的toString()方法。