当你必须遍历一个集合并用分隔符将每个数据组成一个字符串时,你总是会在最后得到一个额外的分隔符,例如:

for (String serverId : serverIds) {
  sb.append(serverId);
   sb.append(",");
}

给出类似serverId_1 serverId_2 serverId_3

我想删除StringBuilder中的最后一个字符(不转换它,因为在这个循环之后我仍然需要它)。


当前回答

我发现自己经常这样做,所以我为3种主要的附加分隔符技术写了一个基准测试: (具有适当预热和100轮100,000次迭代的基准测试)

“附加”

static void appendAfter()
{
    sb.append('{');
    for (int i = 0; i < 10; i++)
    {
        sb.append('"');
        sb.append(i);
        sb.append('"');
        sb.append(':');
        sb.append(i);
        sb.append(',');
    }
    sb.setLength(sb.length() - 1);
    sb.append('}');
}

“添加”

static void appendBefore()
{
    sb.append('{');
    String delimiter = "";
    for (int i = 0; i < 10; i++)
    {
        sb.append(delimiter);
        sb.append('"');
        sb.append(i);
        sb.append('"');
        sb.append(':');
        sb.append(i);
        delimiter = ",";
    }
    sb.append('}');
}

“附加也许”

static void appendMaybe()
{
    sb.append('{');
    for (int i = 0; i < 10; i++)
    {
        sb.append('"');
        sb.append(i);
        sb.append('"');
        sb.append(':');
        sb.append(i);
        if (i < 9)
        {
            sb.append(',');
        }
    }
    sb.append('}');
}

我得到了以下结果:

Platform Append After Append Before Append Maybe
Windows Server 2016, Java 11 - Hotspot 26ms 40ms 26ms
Windows Server 2016, Java 8 - Hotspot 27ms 36ms 21ms
Windows Server 2016, Java 11 - OpenJ9 63ms 81ms 59ms
Windows Server 2016, Java 8 - OpenJ9 66ms 64ms 55ms

除了最快之外,我认为“Append Maybe”实现最好地展示了代码的意图。这通常比每次迭代获得的纳秒分数更重要。

我把基准代码留在这里,以防有人想在自己的平台上尝试它。如果你这样做,请贡献你的结果!

其他回答

这里有另一个解决方案:

for(String serverId : serverIds) {
   sb.append(",");
   sb.append(serverId); 
}

String resultingString = "";
if ( sb.length() > 1 ) {
    resultingString = sb.substring(1);
}

另外,

StringBuilder result = new StringBuilder();
for(String string : collection) {
    result.append(string);
    result.append(',');
}
return result.substring(0, result.length() - 1) ;

其他人指出了deleteCharAt方法,但这里有另一种替代方法:

String prefix = "";
for (String serverId : serverIds) {
  sb.append(prefix);
  prefix = ",";
  sb.append(serverId);
}

或者,使用来自Guava的Joiner类:)

从Java 8开始,StringJoiner是标准JRE的一部分。

您可以尝试使用'Joiner'类,而不是从生成的文本中删除最后一个字符;

                List<String> textList = new ArrayList<>();
                textList.add("text1");
                textList.add("text2");
                textList.add("text3");

                Joiner joiner = Joiner.on(",").useForNull("null");
                String output = joiner.join(textList);

               //output : "text1,text2,text3"

还有另一种选择:

public String join(Collection<String> collection, String seperator) {
    if (collection.isEmpty()) return "";

    Iterator<String> iter = collection.iterator();
    StringBuilder sb = new StringBuilder(iter.next());
    while (iter.hasNext()) {
        sb.append(seperator);
        sb.append(iter.next());
    }

    return sb.toString();
}