连接字符串对象列表的最佳方法?(复制)

时间:2023-01-27 23:59:01

This question already has an answer here:

这个问题已经有了答案:

What is the best way to concatenate a list of String objects? I am thinking of doing this way:

连接字符串对象列表的最佳方式是什么?我想这样做:

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?

有什么想法/评论?

19 个解决方案

#1


43  

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.

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

#2


273  

Use one of the the StringUtils.join methods in Apache Commons Lang.

使用其中一个字符串。在Apache Commons Lang中加入方法。

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);

#3


95  

Using Java 8+

使用Java 8 +

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

or even

甚至

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

#4


39  

A variation on codefin's answer

科德芬的回答有变化

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();                           
}

#5


21  

If you are developing for Android, there is TextUtils.join provided by the SDK.

如果你正在为Android开发,有TextUtils。SDK提供的连接。

#6


15  

Guava is a pretty neat library from Google:

番石榴是一个非常整洁的图书馆,从谷歌:

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

#7


12  

This is the most elegant and clean way I've found so far:

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

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

#8


4  

Have you seen this Coding Horror blog entry?

你见过这个编码恐怖的博客条目吗?

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.

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

#9


4  

I prefer String.join(list) in Java 8

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

#10


3  

Rather than depending on ArrayList.toString() implementation, you could write a one-liner, if you are using java 8:

如果您使用的是java 8,您可以编写一行代码,而不是依赖于ArrayList.toString()实现:

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

If you prefer using StringBuffer instead of String since String::concat has a runtime of O(n^2), you could convert every String to StringBuffer first.

如果你喜欢使用StringBuffer代替字符串从字符串::concat的O(n ^ 2)运行时,您可以将每个字符串转换成StringBuffer。

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

#11


2  

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。因此,您的方法可能节省了几行代码,但代价是额外的字符串操作。这个权衡是好是坏取决于你。

#12


2  

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()方法。

#13


2  

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 ();
}

#14


2  

Next variation on Peter Lawrey's answer without initialization of a new string every loop turn

下一个变化在彼得劳里的回答没有初始化一个新的字符串每循环

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();
}

#15


1  

ArrayList inherits its toString()-method from AbstractCollection, ie:

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(", ");
    }
}

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);
}

#16


1  

In java 8 you can also use a reducer, something like:

在java 8中,您还可以使用还原剂,比如:

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

#17


0  

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 Arraylists reallocation of memory might be a bit slower than StringBuilder.

根据性能的需要和要添加的元素的数量,这可能是一个不错的解决方案。如果元素的数量很高,那么arraylist内存的重新分配可能会比StringBuilder慢一点。

#18


0  

Using the Functional Java library, import these:

使用函数式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_()), ", ");
}

#19


0  

if you have json in your dependencies.you can use new JSONArray(list).toString()

如果您的依赖项中有json。可以使用新的JSONArray(list).toString()

#1


43  

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.

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

#2


273  

Use one of the the StringUtils.join methods in Apache Commons Lang.

使用其中一个字符串。在Apache Commons Lang中加入方法。

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);

#3


95  

Using Java 8+

使用Java 8 +

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

or even

甚至

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

#4


39  

A variation on codefin's answer

科德芬的回答有变化

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();                           
}

#5


21  

If you are developing for Android, there is TextUtils.join provided by the SDK.

如果你正在为Android开发,有TextUtils。SDK提供的连接。

#6


15  

Guava is a pretty neat library from Google:

番石榴是一个非常整洁的图书馆,从谷歌:

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

#7


12  

This is the most elegant and clean way I've found so far:

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

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

#8


4  

Have you seen this Coding Horror blog entry?

你见过这个编码恐怖的博客条目吗?

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.

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

#9


4  

I prefer String.join(list) in Java 8

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

#10


3  

Rather than depending on ArrayList.toString() implementation, you could write a one-liner, if you are using java 8:

如果您使用的是java 8,您可以编写一行代码,而不是依赖于ArrayList.toString()实现:

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

If you prefer using StringBuffer instead of String since String::concat has a runtime of O(n^2), you could convert every String to StringBuffer first.

如果你喜欢使用StringBuffer代替字符串从字符串::concat的O(n ^ 2)运行时,您可以将每个字符串转换成StringBuffer。

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

#11


2  

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。因此,您的方法可能节省了几行代码,但代价是额外的字符串操作。这个权衡是好是坏取决于你。

#12


2  

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()方法。

#13


2  

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 ();
}

#14


2  

Next variation on Peter Lawrey's answer without initialization of a new string every loop turn

下一个变化在彼得劳里的回答没有初始化一个新的字符串每循环

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();
}

#15


1  

ArrayList inherits its toString()-method from AbstractCollection, ie:

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(", ");
    }
}

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);
}

#16


1  

In java 8 you can also use a reducer, something like:

在java 8中,您还可以使用还原剂,比如:

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

#17


0  

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 Arraylists reallocation of memory might be a bit slower than StringBuilder.

根据性能的需要和要添加的元素的数量,这可能是一个不错的解决方案。如果元素的数量很高,那么arraylist内存的重新分配可能会比StringBuilder慢一点。

#18


0  

Using the Functional Java library, import these:

使用函数式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_()), ", ");
}

#19


0  

if you have json in your dependencies.you can use new JSONArray(list).toString()

如果您的依赖项中有json。可以使用新的JSONArray(list).toString()