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


当前回答

Java 8 之前:

Apache的commons lang在这里是你的朋友——它提供了一个连接方法,非常类似于你在Ruby中引用的方法:

StringUtils.join (java.lang.Iterable字符)


Java 8:

Java 8通过StringJoiner和String.join()提供了开箱即用的连接。下面的代码片段展示了如何使用它们:

StringJoiner

StringJoiner joiner = new StringJoiner(",");
joiner.add("01").add("02").add("03");
String joinedString = joiner.toString(); // "01,02,03"

字符串。join(CharSequence分隔符,CharSequence…元素)

String joinedString = String.join(" - ", "04", "05", "06"); // "04 - 05 - 06"

字符串。join(CharSequence分隔符,Iterable<?扩展CharSequence>元素

List<String> strings = new LinkedList<>();
strings.add("Java");strings.add("is");
strings.add("cool");
String message = String.join(" ", strings);
//message returned is: "Java is cool"

其他回答

还有一个最小值(如果你只是为了连接字符串而不想将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();
}

我会使用谷歌集合。有一个很好的Join工具。 http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/base/Join.html

但如果我想自己写,

package util;

import java.util.ArrayList;
import java.util.Iterable;
import java.util.Collections;
import java.util.Iterator;

public class Utils {
    // accept a collection of objects, since all objects have toString()
    public static String join(String delimiter, Iterable<? extends Object> objs) {
        if (objs.isEmpty()) {
            return "";
        }
        Iterator<? extends Object> iter = objs.iterator();
        StringBuilder buffer = new StringBuilder();
        buffer.append(iter.next());
        while (iter.hasNext()) {
            buffer.append(delimiter).append(iter.next());
        }
        return buffer.toString();
    }

    // for convenience
    public static String join(String delimiter, Object... objs) {
        ArrayList<Object> list = new ArrayList<Object>();
        Collections.addAll(list, objs);
        return join(delimiter, list);
    }
}

我认为它更好地用于对象集合,因为现在你不必在加入它们之前将对象转换为字符串。

izb版本的速度略有提高:

public static String join(String[] strings, char del)
{
    StringBuilder sb = new StringBuilder();
    int len = strings.length;

    if(len > 1) 
    {
       len -= 1;
    }else
    {
       return strings[0];
    }

    for (int i = 0; i < len; i++)
    {
       sb.append(strings[i]).append(del);
    }

    sb.append(strings[i]);

    return sb.toString();
}

为什么你不在Java中做你在ruby中做的同样的事情,那就是在你将所有的片段添加到数组后才创建分隔符分隔的字符串?

ArrayList<String> parms = new ArrayList<String>();
if (someCondition) parms.add("someString");
if (anotherCondition) parms.add("someOtherString");
// ...
String sep = ""; StringBuffer b = new StringBuffer();
for (String p: parms) {
    b.append(sep);
    b.append(p);
    sep = "yourDelimiter";
}

你可能想要在一个单独的帮助方法中移动for循环,并且使用StringBuilder而不是StringBuffer…

编辑:修正了追加的顺序。

修正答案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);
}