Java:将List<String>转换为join()后的String

723

JavaScript有Array.join()方法

js>["Bill","Bob","Steve"].join(" and ")
Bill and Bob and Steve

Java有类似这样的东西吗?我知道我可以自己用StringBuilder组合一些东西:

static public String join(List<String> list, String conjunction)
{
   StringBuilder sb = new StringBuilder();
   boolean first = true;
   for (String item : list)
   {
      if (first)
         first = false;
      else
         sb.append(conjunction);
      sb.append(item);
   }
   return sb.toString();
}

..但是如果JDK中已经有类似的内容,那么这样做就没有意义了。


1
请参见此问题以获取有关Java中构建带有分隔符的字符串的最佳方法的列表。 - Casebash
19
虽然与此无严格相关之处,但安卓系统中的TextUtils类自带一个join函数:http://developer.android.com/reference/android/text/TextUtils.html#join(java.lang.CharSequence, java.lang.Iterable)。 - Xavi
18
Java 8新增了String.join()方法。如果你使用Java 8或更高版本,可以查看此答案 https://dev59.com/dnI-5IYBdhLWcg3wpaB1#22577565 - micha
23个回答

10

使用java.util.StringJoiner的Java 8解决方案

Java 8引入了StringJoiner类。但因为这是Java,你仍然需要写一些样板代码。

StringJoiner sj = new StringJoiner(" and ", "" , "");
String[] names = {"Bill", "Bob", "Steve"};
for (String name : names) {
   sj.add(name);
}
System.out.println(sj);

如果您使用更方便的方法String.join(),则无需编写任何样板文件。 - Andy Thomas

9

7

使用Java 1.8,可以使用流(Stream)。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

List<String> list = Arrays.asList("Bill","Bob","Steve").
String str = list.stream().collect(Collectors.joining(" and "));

7
你可以这样做:
String aToString = java.util.Arrays.toString(anArray);
// Do not need to do this if you are OK with '[' and ']'
aToString = aToString.substring(1, aToString.length() - 1);

或者一行代码(仅当您不想要'['和']'时)

String aToString = java.util.Arrays.toString(anArray).substring(1).replaceAll("\\]$", "");

希望这可以帮助您。

1
这不会附加所选的连接词。 - hexium
糟糕!对不起,我没有注意到。 - NawaMan

6

使用纯JDK的有趣方法,在一行代码中实现:

String[] array = new String[] { "Bill", "Bob", "Steve","[Bill]","1,2,3","Apple ][" };
String join = " and ";

String joined = Arrays.toString(array).replaceAll(", ", join)
        .replaceAll("(^\\[)|(\\]$)", "");

System.out.println(joined);

输出:

Bill、Bob、Steve、[Bill]、1、2、3和Apple ][


一种不太完美且不太有趣的方法!

String[] array = new String[] { "7, 7, 7","Bill", "Bob", "Steve", "[Bill]",
        "1,2,3", "Apple ][" };
String join = " and ";

for (int i = 0; i < array.length; i++) array[i] = array[i].replaceAll(", ", "~,~");
String joined = Arrays.toString(array).replaceAll(", ", join)
        .replaceAll("(^\\[)|(\\]$)", "").replaceAll("~,~", ", ");

System.out.println(joined);

输出:

7、7、7以及比尔、鲍勃、史蒂夫、[比尔]、1、2、3和苹果 ][


尝试使用 "[Bill]", "1,2,3" 和 "Apple ][" 进行测试。可以有创造性,但也可能存在不正确的情况。 - Jason S
1
现在使用“〜,〜”进行尝试。你无法使具有这种架构的程序完全防弹。 - Jason S
是的,我知道...我已经取消了踩的操作。但你应该更加谨慎地考虑在这里发布答案,特别是对于那些几年前的问题。答案不仅对原始发帖人有立即的用处,而且还会出现在谷歌搜索结果中。(实际上,对于几年前的问题,新答案可能对原始发帖人没有任何价值。) 有缺陷或错误的解决方案可能会对后来的人造成伤害,因为他们找到时已经脱离了上下文。 - Jason S
1
我从其他人的帖子中学到了很多,就像我的帖子一样,它们并不完美,但真正充满了知识和侧面思考。对于其他人来说,请放松心态,每个人都必须理解他们代码的每一行所做的事情。记住,编程就像艺术一样,即使是每一行代码,也代表着程序员的个性。是的,我不会在生产中使用这段代码! - Daniel De León

4

编辑

我也注意到了 toString() 的实现问题,以及包含分隔符的元素,但我认为这可能只是我的多虑。

既然有两个评论提到了这个问题,我决定修改我的答案:

static String join( List<String> list , String replacement  ) {
    StringBuilder b = new StringBuilder();
    for( String item: list ) { 
        b.append( replacement ).append( item );
    }
    return b.toString().substring( replacement.length() );
}

这看起来与原始问题非常相似。

因此,如果您不想向项目添加整个jar文件,则可以使用此选项。

我认为您的原始代码没有任何问题。实际上,每个人都建议的替代方案看起来几乎相同(尽管它执行了许多附加验证)。

这是它,连同Apache 2.0许可证一起。

public static String join(Iterator iterator, String separator) {
    // handle null, zero and one elements before building a buffer
    if (iterator == null) {
        return null;
    }
    if (!iterator.hasNext()) {
        return EMPTY;
    }
    Object first = iterator.next();
    if (!iterator.hasNext()) {
        return ObjectUtils.toString(first);
    }

    // two or more elements
    StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
    if (first != null) {
        buf.append(first);
    }

    while (iterator.hasNext()) {
        if (separator != null) {
            buf.append(separator);
        }
        Object obj = iterator.next();
        if (obj != null) {
            buf.append(obj);
        }
    }
    return buf.toString();
}

现在我们知道了,感谢开源。


现在这个方法可以工作,但是你不能确定 List.toString() 在未来的行为。我从不相信 toString() 操作除了打印有关所讨论对象的一些信息字符串之外的任何操作。为了辩护你,你并不是唯一提出这种解决方案的人。 - Hans Doggen
如果列表中的元素内容包含子字符串 ", ",该怎么办? - Bart Kiers
@Hans和@Bart:你们说得对。我以为没人会注意到:P 我正在修改我的答案。 - OscarRyz
这取决于使用情况。对于调试目的,我认为toString()就足够了...只要你不依赖于特定的格式。即使如此,如果你为你的代码编写测试,任何未来的更改都将被捕获。 - akostadinov

4
如果您正在使用Eclipse Collections(以前称为GS Collections),则可以使用makeString()方法。
List<String> list = Arrays.asList("Bill", "Bob", "Steve");

String string = ListAdapter.adapt(list).makeString(" and ");

Assert.assertEquals("Bill and Bob and Steve", string);

如果您可以将您的List转换为Eclipse Collections类型,那么您就可以摆脱适配器了。
MutableList<String> list = Lists.mutable.with("Bill", "Bob", "Steve");
String string = list.makeString(" and ");

如果您只需要一个逗号分隔的字符串,可以使用不带参数的 makeString() 版本。
Assert.assertEquals(
    "Bill, Bob, Steve", 
    Lists.mutable.with("Bill", "Bob", "Steve").makeString());

注意: 我是 Eclipse Collections 的提交者。


4

2

谷歌的Guava API也有.join()方法,但是(显而易见的是其他回复中已经提到),Apache Commons在这里几乎是标准。


2

Java 8 带来了

Collectors.joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

通过使用前缀+后缀来处理空值的方法。

可以按照以下方式使用:

String s = stringList.stream().collect(Collectors.joining(" and ", "prefix_", "_suffix"))
Collectors.joining(CharSequence delimiter) 方法只是在内部调用 joining(delimiter, "", "")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接