当我在一个Java应用程序中工作时,我最近需要组装一个以逗号分隔的值列表,以传递给另一个web服务,而不知道预先会有多少个元素。我能想到的最好的是这样的:

public String appendWithDelimiter( String original, String addition, String delimiter ) {
    if ( original.equals( "" ) ) {
        return addition;
    } else {
        return original + delimiter + addition;
    }
}

String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );

我意识到这不是特别有效,因为到处都在创建字符串,但我追求的是清晰而不是优化。

在Ruby中,我可以这样做,这感觉要优雅得多:

parameterArray = [];
parameterArray << "elementName" if condition;
parameterArray << "anotherElementName" if anotherCondition;
parameterString = parameterArray.join(",");

但是由于Java缺少join命令,我找不到任何等价的命令。

那么,在Java中最好的方法是什么呢?


当前回答

如果使用Eclipse Collections,则可以使用makeString()或appendString()。

makeString()返回String表示形式,类似于toString()。

它有三种形式

makeString(开始,分隔符,结束) makeString(separator)默认开始和结束为空字符串 makeString()默认分隔符为","(逗号和空格)

代码示例:

MutableList<Integer> list = FastList.newListWith(1, 2, 3);
assertEquals("[1/2/3]", list.makeString("[", "/", "]"));
assertEquals("1/2/3", list.makeString("/"));
assertEquals("1, 2, 3", list.makeString());
assertEquals(list.toString(), list.makeString("[", ", ", "]"));

appendString()类似于makeString(),但它附加到Appendable(如StringBuilder),并且是空的。它有同样的三种形式,有一个额外的第一个参数,可追加的。

MutableList<Integer> list = FastList.newListWith(1, 2, 3);
Appendable appendable = new StringBuilder();
list.appendString(appendable, "[", "/", "]");
assertEquals("[1/2/3]", appendable.toString());

如果不能将集合转换为Eclipse Collections类型,只需使用相关的适配器对其进行调整。

List<Object> list = ...;
ListAdapter.adapt(list).makeString(",");

注意:我是Eclipse集合的提交者。

其他回答

您可以编写一个连接风格的实用程序方法,它可以在java.util.Lists上工作

public static String join(List<String> list, String delim) {

    StringBuilder sb = new StringBuilder();

    String loopDelim = "";

    for(String s : list) {

        sb.append(loopDelim);
        sb.append(s);            

        loopDelim = delim;
    }

    return sb.toString();
}

然后像这样使用它:

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

    if( condition )        list.add("elementName");
    if( anotherCondition ) list.add("anotherElementName");

    join(list, ",");

使用Java 5变量参数,所以你不需要将所有的字符串显式地填充到一个集合或数组中:

import junit.framework.Assert;
import org.junit.Test;

public class StringUtil
{
    public static String join(String delim, String... strings)
    {
        StringBuilder builder = new StringBuilder();

        if (strings != null)
        {
            for (String str : strings)
            {
                if (builder.length() > 0)
                {
                    builder.append(delim).append(" ");
                }
                builder.append(str);
            }
        }           
        return builder.toString();
    }
    @Test
    public void joinTest()
    {
        Assert.assertEquals("", StringUtil.join(",", null));
        Assert.assertEquals("", StringUtil.join(",", ""));
        Assert.assertEquals("", StringUtil.join(",", new String[0]));
        Assert.assertEquals("test", StringUtil.join(",", "test"));
        Assert.assertEquals("foo, bar", StringUtil.join(",", "foo", "bar"));
        Assert.assertEquals("foo, bar, x", StringUtil.join(",", "foo", "bar", "x"));
    }
}

修正答案Rob Dickerson。

更容易使用:

public static String join(String delimiter, String... values)
{
    StringBuilder stringBuilder = new StringBuilder();

    for (String value : values)
    {
        stringBuilder.append(value);
        stringBuilder.append(delimiter);
    }

    String result = stringBuilder.toString();

    return result.isEmpty() ? result : result.substring(0, result.length() - 1);
}

所以你可能会做一些事情来获得你想要的感觉:

1)扩展List类-并将join方法添加到其中。join方法将简单地完成连接和添加分隔符(可以是join方法的参数)的工作。

2)看起来java7将在Java中添加扩展方法——它允许你将一个特定的方法附加到一个类上:所以你可以编写join方法并将其作为扩展方法添加到List甚至Collection中。

解决方案1可能是目前唯一现实的解决方案,因为Java 7还没有出来:)但它应该工作得很好。

要使用这两种方法,你只需要像往常一样将所有项目添加到列表或集合中,然后调用新的自定义方法来“加入”它们。

我个人经常使用以下简单的解决方案进行日志记录:

List lst = Arrays.asList("ab", "bc", "cd");
String str = lst.toString().replaceAll("[\\[\\]]", "");