删除StringBuilder的最后一个字符?

时间:2010-08-03 09:41:28

标签: java stringbuilder

当你必须遍历一个集合并用分隔符分隔每个数据的字符串时,你最终总会得到一个额外的分隔符,例如。

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

提供的内容如下: serverId_1,serverId_2,serverId_3,

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

19 个答案:

答案 0 :(得分:573)

其他人已指出deleteCharAt方法,但这是另一种替代方法:

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

或者,使用Joiner中的Guava类:)

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

答案 1 :(得分:373)

另一个简单的解决方案是:

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

更复杂的解决方案:

上述解决方案假定sb.length() > 0 ...即要删除“最后一个字符”。如果你不能做出这个假设,和/或你不能处理如果假设不正确会发生的异常,那么首先检查StringBuilder的长度; e.g。

// Readable version
if (sb.length() > 0) {
   sb.setLength(sb.length() - 1);
}

// Concise but harder-to-read version of the above.
sb.setLength(Math.max(sb.length() - 1, 0));

答案 2 :(得分:153)

sb.deleteCharAt(sb.length() - 1) 

答案 3 :(得分:55)

从Java 8开始,String类有一个静态方法join。第一个参数是你想要在每对字符串之间的字符串,第二个参数是Iterable<CharSequence>(它们都是接口,所以像List<String>这样的东西。所以你可以这样做:

String.join(",", serverIds);

同样在Java 8中,您可以使用新的StringJoiner类,以便在您拥有要放入的完整元素列表之前开始构建字符串。

答案 4 :(得分:33)

在这种情况下,

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

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

答案 5 :(得分:28)

只需获取最后一个字符的位置。

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

由于lastIndexOf会执行反向搜索,并且您知道它会在第一次尝试时找到,因此性能不会成为问题。

修改

由于我不断提高答案(感谢大家),因此值得考虑:

Java 8 之后,使用StringJoiner会更加清晰明了。 它有一个简单分隔符的方法,以及前缀和后缀的重载。

从这里取得的例子:example

使用简单分隔符的示例:

    StringJoiner mystring = new StringJoiner("-");    

    // Joining multiple strings by using add() method  
    mystring.add("Logan");  
    mystring.add("Magneto");  
    mystring.add("Rogue");  
    mystring.add("Storm");  

    System.out.println(mystring);

输出:

  

洛根-磁盗贼风暴

带后缀和前缀的示例:

    StringJoiner mystring = new StringJoiner(",", "(", ")");    

    // Joining multiple strings by using add() method  
    mystring.add("Negan");  
    mystring.add("Rick");  
    mystring.add("Maggie");  
    mystring.add("Daryl");  

    System.out.println(mystring);

输出

  

(Negan,瑞克,麦琪,达里尔)

答案 6 :(得分:12)

使用Java-8,您可以使用String类的静态方法

String#join(CharSequence delimiter,Iterable<? extends CharSequence> elements).

public class Test {

    public static void main(String[] args) {

        List<String> names = new ArrayList<>();
        names.add("James");
        names.add("Harry");
        names.add("Roy");
        System.out.println(String.join(",", names));
    }
}

<强>输出

James,Harry,Roy

答案 7 :(得分:10)

另一种选择

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

答案 8 :(得分:7)

可替换地,

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

答案 9 :(得分:5)

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

答案 10 :(得分:4)

另一种选择:

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();
}

答案 11 :(得分:3)

为避免prefix重新启动(影响性能),请使用TextUtils.isEmpty:

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

答案 12 :(得分:1)

我正在做类似下面的事情:

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

答案 13 :(得分:1)

stringBuilder.Remove(stringBuilder.Length-1,1);

答案 14 :(得分:1)

您可以尝试使用&#39; Joiner&#39; class而不是从生成的文本中删除最后一个字符;

                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"

答案 15 :(得分:0)

这是另一种解决方案:

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

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

答案 16 :(得分:0)

我个人喜欢在最后附加一个退格字符(或者更长的“分隔符”):

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

sb.append('\b');

请注意,它有问题:

  • 如何显示\b取决于环境,
  • length()内容的String可能与“可见”字符的长度不同

\b看起来没问题且长度无关紧要时,例如登录到控制台,这对我来说似乎已经足够了。

答案 17 :(得分:0)

由于您知道要删除的字符,因此可以使用此

{{1}}

答案 18 :(得分:0)

我发现自己这样做了很多,所以我为 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('}');
}

我得到了以下结果:

<头>
平台 追加 附加在前 附加可能
Windows Server 2016,Java 11 - 热点 26 毫秒 40 毫秒 26 毫秒
Windows Server 2016,Java 8 - 热点 27 毫秒 36 毫秒 21 毫秒
Windows Server 2016,Java 11 - OpenJ9 63 毫秒 81 毫秒 59 毫秒
Windows Server 2016,Java 8 - OpenJ9 66 毫秒 64 毫秒 55 毫秒

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

我留下了基准代码 here,以防有人想在他们的平台上试用。如果你这样做,请在上面贡献你的结果!