1. 概述
在这个教程中,我们将探讨是否为了效率重用StringBuilder
对象。我们将指导如何重用StringBuilder
并解释其益处。
2. 优势
2.1. 优化对象创建
在Java中,由于字符串是不可变的,使用StringBuilder
连接不同字符串通常可以避免不必要的对象创建。重用StringBuilder
本身也可以避免额外的内存分配和垃圾回收开销。
2.2. 提高性能
StringBuilder
对象是可变的,这使得我们可以在不创建新对象的情况下多次修改对象,显著提高了性能。
2.3. 减少内存使用
字符串对象是不可变的,这意味着它们在创建后不能被修改。当对字符串进行修改时,会创建新的对象,增加内存使用。通过使用StringBuilder
实例,开发者可以避免不必要的对象创建,减少应用程序使用的内存量。
2.4. 改善缓存可靠性
每次应用程序创建新对象时,它可能在每次分配时位于不同的内存位置,导致缓存缺失,降低性能。通过重用StringBuilder
实例,可以重复使用同一个对象,提高缓存利用率,从而提升性能。
3. 示例
在我们的第一个示例中,我们在每次循环迭代中创建一个新的StringBuilder
对象:
for (int i = 0; i < 100; i++) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("baeldung");
stringBuilder.toString();
}
另一种方法是反复使用同一个StringBuilder
对象。为此,我们需要在每次循环迭代的末尾调用delete()
方法,删除StringBuilder
中的整个字符数组:
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 100; i++) {
stringBuilder.append("baeldung");
stringBuilder.toString();
stringBuilder.delete(0, stringBuilder.length());
}
而不用删除底层的字符数组,我们也可以在每次迭代后将StringBuilder
的长度设为0:
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 100; i++) {
stringBuilder.append("baeldung");
stringBuilder.toString();
stringBuilder.setLength(0);
}
让我们比较一下上述示例在简短基准测试中的差异:
Benchmark Mode Cnt Score Error Units
Example 1: new StringBuilder object ss 10 210,661 ± 15,237 ms/op
Example 2: reuse StringBuilder with delete() ss 10 185,908 ± 7,802 ms/op
Example 3: reuse StringBuilder with setLength() ss 10 164,323 ± 1,909 ms/op
如预期,每次迭代的对象创建是最慢的。我们还可以看到,使用setLength(0)
的方法比delete(0, stringBuilder.length())
更快。这是因为通过setLength()
,我们只改变了StringBuilder
对象的计数字段的值,这个操作非常快。而delete()
方法则需要StringBuilder
对象删除指定范围的字符,这涉及到更复杂的数组移动操作。
在我们的例子中,通过传入0和最大长度,整个字符数组被删除。因此,使用setLength()
方法通常更快地达到相同结果,因为数组的移动更复杂。
4. 何时重用StringBuilder
重要的是,并非所有字符串操作都需要StringBuilder
。我们可以执行简单的操作,如无StringBuilder
的字符串连接。也不必对所有操作都使用可重用的StringBuilder
。对于涉及大量操作或迭代次数的复杂字符串操作,我们应该使用可重用的StringBuilder
。
在并发应用中,我们也需要确保线程安全。如果没有适当的同步,多个线程可能会使用同一个StringBuilder
对象,导致意外的行为。开发者可以通过同步方法或锁来防止竞争条件,确保线程安全。或者,类或线程可以在本地范围内仅重用StringBuilder
对象。
有时,如果性能不是很重要,放弃重用StringBuilder
和由此带来的性能提升也是有意义的,以确保代码易于理解和阅读。
5. 总结
在这篇文章中,我们讨论了重用StringBuilder
的优势,并给出了如何实现的具体示例。总的来说,重用StringBuilder
有助于减少开销并提高性能。
如往常一样,示例代码可在GitHub上找到。