1. 概述

在这个教程中,我们将介绍几种清除StringBuilderStringBuffer的方法,并详细解释它们的工作原理。

2. 清除StringBuilder

2.1. 使用setLength方法

setLength方法会更新StringBuilder的内部长度。在操作StringBuilder时,它会忽略长度之后的所有元素。因此,将长度设置为0可以清空内容:

@Test
void whenSetLengthToZero_ThenStringBuilderIsCleared() {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("Hello World");
    int initialCapacity = stringBuilder.capacity();
    stringBuilder.setLength(0);
    assertEquals("", stringBuilder.toString());
    assertEquals(initialCapacity, stringBuilder.capacity();
}

请注意,在调用setLength方法后,StringBuilder的容量保持不变。

2.2. 使用delete方法

delete方法在后台使用System.arraycopy。所有在开始索引之前或结束索引之后的索引会被复制到同一个StringBuilder中。

因此,如果使用开始索引为0和结束索引等于StringBuilder长度的delete方法,将进行以下操作:

  • 在0之前没有索引:无内容。
  • stringBuilder.length()之后的索引:无内容。

结果是,StringBuilder的所有内容都会被删除:

@Test
void whenDeleteAll_ThenStringBuilderIsCleared() {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("Hello World");
    int initialCapacity = stringBuilder.capacity();
    stringBuilder.delete(0, stringBuilder.length());
    assertEquals("", stringBuilder.toString());
    assertEquals(initialCapacity, stringBuilder.capacity();
}

setLength方法相同,内容删除后对象的容量保持不变。并且这个过程不涉及新对象的创建。

3. 清除StringBuffer

StringBuilder适用的所有方法对StringBuffer也适用。关于对象容量的评论同样有效。让我们通过setLength方法来举例说明:

@Test
void whenSetLengthToZero_ThenStringBufferIsCleared() {
    StringBuffer stringBuffer = new StringBuffer();
    stringBuffer.append("Hello World");
    int initialCapacity = stringBuffer.capacity();
    stringBuffer.setLength(0);
    assertEquals("", stringBuffer.toString());
    assertEquals(initialCapacity, stringBuffer.capacity();
}

也可以使用delete方法:

@Test
void whenDeleteAll_ThenStringBufferIsCleared() {
    StringBuffer stringBuffer = new StringBuffer();
    stringBuffer.append("Hello World");
    int initialCapacity = stringBuffer.capacity();
    stringBuffer.delete(0, stringBuffer.length());
    assertEquals("", stringBuffer.toString());
    assertEquals(initialCapacity, stringBuffer.capacity();
}

4. 性能

让我们使用JMH快速进行性能比较。以下是StringBuilder的三种方法的比较:

@State(Scope.Benchmark)
public static class MyState {
    final String HELLO = "Hello World";
    final StringBuilder sb = new StringBuilder().append(HELLO);
}

@Benchmark
public void evaluateSetLength(Blackhole blackhole, MyState state) {
    state.sb.setLength(0);
    blackhole.consume(state.sb.toString());
}

@Benchmark
public void evaluateDelete(Blackhole blackhole, MyState state) {
    state.sb.delete(0, state.sb.length());
    blackhole.consume(state.sb.toString());
}

我们测量的是每秒操作次数。这个基准得出的结果如下:

Benchmark                  Mode   Cnt         Score          Error  Units
evaluateDelete             thrpt   25  67943684.417 ± 18116791.770  ops/s
evaluateSetLength          thrpt   25  37310891.158 ±   994382.978  ops/s

可以看到,delete方法几乎比另一种方法快了一倍,耗时最少。

5. 总结

在这篇文章中,我们详细介绍了清除StringBuilderStringBuffer的三种方法。

如往常一样,代码可在GitHub上找到。