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

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

给出类似serverId_1 serverId_2 serverId_3

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


当前回答

我正在做的事情如下:

    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < value.length; i++) {
        stringBuilder.append(values[i]);
        if (value.length-1) {
            stringBuilder.append(", ");
        }
    }

其他回答

我发现自己经常这样做,所以我为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”实现最好地展示了代码的意图。这通常比每次迭代获得的纳秒分数更重要。

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

StringBuilder sb = new StringBuilder();
sb.append("abcdef");
sb.deleteCharAt(sb.length() - 1);
assertEquals("abcde",sb.toString());
// true

在这种情况下,

sb.setLength(sb.length() - 1);

是可取的,因为它只是将最后一个值分配给'\0',而删除最后一个字符的System.arraycopy

为了避免前缀的reinit(影响性能),使用TextUtils.isEmpty:

            String prefix = "";
            for (String item : list) {
                sb.append(prefix);
                if (TextUtils.isEmpty(prefix))
                    prefix = ",";
                sb.append(item);
            }

我正在做的事情如下:

    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < value.length; i++) {
        stringBuilder.append(values[i]);
        if (value.length-1) {
            stringBuilder.append(", ");
        }
    }