当我在一个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中最好的方法是什么呢?


当前回答

你把事情搞得更复杂了。让我们从例子的结尾开始:

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

通过使用StringBuilder而不是String的小变化,这就变成了:

StringBuilder parameterString = new StringBuilder();
if (condition) parameterString.append("elementName").append(",");
if (anotherCondition) parameterString.append("anotherElementName").append(",");
...

当你完成后(我假设你还必须检查一些其他条件),只要确保你用这样的命令删除了后面的逗号:

if (parameterString.length() > 0) 
    parameterString.deleteCharAt(parameterString.length() - 1);

最后,得到你想要的字符串

parameterString.toString();

您还可以替换第二个调用中的“,”,以附加一个可以设置为任何内容的通用分隔符字符串。如果你有一个列表,你知道你需要附加的东西(非有条件的),你可以把这段代码放在一个接受字符串列表的方法中。

其他回答

您可以泛化它,但正如您所说,Java中没有连接。

这样可能效果更好。

public static String join(Iterable<? extends CharSequence> s, String delimiter) {
    Iterator<? extends CharSequence> iter = s.iterator();
    if (!iter.hasNext()) return "";
    StringBuilder buffer = new StringBuilder(iter.next());
    while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
    return buffer.toString();
}

还有一个最小值(如果你只是为了连接字符串而不想将Apache Commons或Gauva包含到项目依赖项中)

/**
 *
 * @param delim : String that should be kept in between the parts
 * @param parts : parts that needs to be joined
 * @return  a String that's formed by joining the parts
 */
private static final String join(String delim, String... parts) {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < parts.length - 1; i++) {
        builder.append(parts[i]).append(delim);
    }
    if(parts.length > 0){
        builder.append(parts[parts.length - 1]);
    }
    return builder.toString();
}

如果使用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 8中,你可以这样做:

list.stream().map(Object::toString)
        .collect(Collectors.joining(delimiter));

如果列表有空值,你可以使用:

list.stream().map(String::valueOf)
        .collect(Collectors.joining(delimiter))

它还支持前缀和后缀:

list.stream().map(String::valueOf)
        .collect(Collectors.joining(delimiter, prefix, suffix));

您的方法还不错,但是您应该使用StringBuffer而不是使用+号。+有一个很大的缺点,就是为每个操作创建了一个新的String实例。你的弦越长,开销就越大。所以使用StringBuffer应该是最快的方法:

public StringBuffer appendWithDelimiter( StringBuffer original, String addition, String delimiter ) {
        if ( original == null ) {
                StringBuffer buffer = new StringBuffer();
                buffer.append(addition);
                return buffer;
        } else {
                buffer.append(delimiter);
                buffer.append(addition);
                return original;
        }
}

创建完字符串后,只需对返回的StringBuffer调用toString()即可。