StringBuffer
和StringBuilder
的主要区别是什么?在决定使用其中任何一个时是否存在性能问题?
StringBuffer
和StringBuilder
的主要区别是什么?在决定使用其中任何一个时是否存在性能问题?
StringBuffer
是同步的,而StringBuilder
则不是。
StringBuilder
比StringBuffer
更快,因为它不是同步的。
下面是一个简单的基准测试:
public class Main {
public static void main(String[] args) {
int N = 77777777;
long t;
{
StringBuffer sb = new StringBuffer();
t = System.currentTimeMillis();
for (int i = N; i --> 0 ;) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
{
StringBuilder sb = new StringBuilder();
t = System.currentTimeMillis();
for (int i = N; i > 0 ; i--) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
}
}
进行测试运行,StringBuffer
用时2241毫秒
,而StringBuilder
用时753毫秒
。
--> 0
,花了我一点时间才意识到它的含义。这种写法实际上可以代替通常的 ...; i>0; i--
语法吗?请注意,我的翻译尽可能保留原文意思,并使其更加易懂,但不包括解释和其他内容。 - Raimund Krämeri -->
在语法上真的很烦人……一开始我以为是箭头,因为有关 ASCII 艺术的注释。 - Sameer Puri基本上,StringBuffer
的方法是同步的,而 StringBuilder
则不是。
这些操作“几乎”相同,但在单个线程中使用同步方法会过度。
这就是基本情况。
引用自 StringBuilder API:
这个类 [StringBuilder] 提供了与 StringBuffer 兼容的 API,但不保证同步。此类设计为在单个线程使用字符串缓冲区时(通常情况下)可替换为 StringBuffer 的替代品。如果可能的话,建议优先使用此类,因为在大多数实现中它将更快。
因此,它的作用是替代它。
与Vector
和ArrayList
发生了同样的事情。
Hashtable
和HashMap
。 - shmosel但需要通过示例来明确区别吗?
StringBuffer
或StringBuilder
除非你真的想要在线程之间共享缓冲区,否则简单地使用StringBuilder
即可。 StringBuilder
是原始同步的 StringBuffer
类的无同步(更少开销=更高效)版本。
StringBuffer
先于StringBuilder
出现。 Sun公司关注所有条件下的正确性,因此他们将其同步以使其在线程安全情况下工作。
StringBuilder
稍后出现。 大多数StringBuffer
的用途都是单线程并且不必要地支付同步成本。
由于StringBuilder
是没有同步功能的可直接替换 StringBuffer
,因此在任何示例中不会有区别。
如果你尝试在线程之间共享,请使用StringBuffer
,但需要考虑是否需要更高级别的同步,例如,您可以在使用StringBuilder
的方法上同步。
首先,让我们看看相似之处: StringBuilder和StringBuffer都是可变的。这意味着您可以在同一位置更改它们的内容。
区别: StringBuffer是可变的并且同步。而StringBuilder是可变的,但默认情况下不同步。
synchronized(同步)的含义: 当某物被同步时,多个线程可以随意访问和修改它而不会有任何问题或副作用。 StringBuffer是同步的,因此您可以在多个线程中使用它而不会有任何问题。
何时使用哪一个? StringBuilder:当您需要一个可修改的字符串,并且仅有一个线程正在访问和修改它时。 StringBuffer:当您需要一个可修改的字符串,并且多个线程正在访问和修改它时。
注意:不要不必要地使用StringBuffer,即如果只有一个线程在修改和访问它,则不要使用它,因为它具有大量用于同步的锁定和解锁代码,这将不必要地占用CPU时间。除非需要,否则不要使用锁定。
public static void main(String[] args) {
String withString ="";
long t0 = System.currentTimeMillis();
for (int i = 0 ; i < 100000; i++){
withString+="some string";
}
System.out.println("strings:" + (System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuffer buf = new StringBuffer();
for (int i = 0 ; i < 100000; i++){
buf.append("some string");
}
System.out.println("Buffers : "+(System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuilder building = new StringBuilder();
for (int i = 0 ; i < 100000; i++){
building.append("some string");
}
System.out.println("Builder : "+(System.currentTimeMillis() - t0));
}
结果:
字符串数量:319740
缓冲区数量:23
构建器数量:7!
因此,构建器比缓冲区更快,并且比字符串拼接要快得多。 现在让我们使用Executor进行多线程处理:
public class StringsPerf {
public static void main(String[] args) {
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
//With Buffer
StringBuffer buffer = new StringBuffer();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(buffer));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Buffer : "+ AppendableRunnable.time);
//With Builder
AppendableRunnable.time = 0;
executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(builder));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Builder: "+ AppendableRunnable.time);
}
static void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // code reduced from Official Javadoc for Executors
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (Exception e) {}
}
}
class AppendableRunnable<T extends Appendable> implements Runnable {
static long time = 0;
T appendable;
public AppendableRunnable(T appendable){
this.appendable = appendable;
}
@Override
public void run(){
long t0 = System.currentTimeMillis();
for (int j = 0 ; j < 10000 ; j++){
try {
appendable.append("some string");
} catch (IOException e) {}
}
time+=(System.currentTimeMillis() - t0);
}
}
StringBuilder 是在 Java 1.5 引入的,因此无法与早期JVM兼容。
根据Javadocs:
StringBuilder 类提供了一个 API,与 StringBuffer 兼容,但没有同步的保证。该类被设计为在单线程中使用字符串缓冲区的地方作为其替代品(通常情况下是这种情况)。在可能的情况下,建议优先使用此类,因为在大多数实现下它将更快。
StringBuilder
。 - Jin Kwon相当不错的问题
以下是我注意到的区别:
StringBuffer:-
StringBuffer is synchronized
StringBuffer is thread-safe
StringBuffer is slow (try to write a sample program and execute it, it will take more time than StringBuilder)
StringBuilder:-
StringBuilder is not synchronized
StringBuilder is not thread-safe
StringBuilder performance is better than StringBuffer.
常见的事情:
两者具有相同的方法和相同的签名。两者都是可变的。
StringBuffer
StringBuilder
StringBuffer
,无需进行其他更改append
两次或append
和toString
,则不安全。 - Peter LawreyStringBuffer
StringBuffer是可变的,这意味着可以更改对象的值。通过StringBuffer创建的对象存储在堆中。StringBuffer具有与StringBuilder相同的方法,但StringBuffer中的每个方法都是同步的,也就是说StringBuffer是线程安全的。
由于这个原因,它不允许两个线程同时访问同一个方法。每个方法一次只能被一个线程访问。
但是,线程安全也有缺点,因为线程安全属性会影响StringBuffer的性能。因此,在调用每个类的相同方法时,StringBuilder比StringBuffer更快。
StringBuffer的值可以更改,这意味着它可以被赋予新值。现在,这是一个最常见的面试问题,即上述类之间的区别。可以使用toString()方法将StringBuffer转换为字符串。
StringBuffer demo1 = new StringBuffer(“Hello”) ;
// The above object stored in heap and its value can be changed .
demo1=new StringBuffer(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuffer
StringBuilder
StringBuilder与StringBuffer相同,它将对象存储在堆中并且也可以修改。StringBuffer和StringBuilder之间的主要区别在于StringBuilder也不是线程安全的。 StringBuilder很快,因为它不是线程安全的。
StringBuilder demo2= new StringBuilder(“Hello”);
// The above object too is stored in the heap and its value can be modified
demo2=new StringBuilder(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuilder