String vs StringBuffer vs StringBuilder

代码实现

String 类是一个final类型的不可变类,所以在对String类进行操作时,都会创建一个新的String类,造成空间和时间的开销。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    }

StringBuilder类 和StringBuffer类均实现了相同的接口和继承了相同的父类,只是StringBuffer的方法上加了synchronized关键字,保证在多线程情况下是线程安全的,其它实现没有差别。

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
{
    @Override
    @HotSpotIntrinsicCandidate
    public StringBuilder append(int i) {
        super.append(i);
        return this;
    }
}

StringBuffer类

 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuffer>, CharSequence
{
    @Override
    @HotSpotIntrinsicCandidate
    public synchronized StringBuffer append(int i) {
        toStringCache = null;
        super.append(i);
        return this;
    }
}

性能对比

通过写代码对比,String的性能比StringBuffer和StringBuiler慢5-10个数量级;
在单线程情况下,StringBuffer的性能反而比StringBuilder快,具体原因有待分析;
在多线程情况下,StringBuilder性能比StringBuffer性能快,因为StringBuffer需要获取对象锁;

测试结果为:

StringBuilder cost:14
MultiStringBuffer cost:102
MultiStringBuilder cost:61
StringBuffer cost:9
String cost:940
@TestInstance(Lifecycle.PER_CLASS)
public class GenericTest {

    @Test
    public void testString() {

        AtomicReference<String> s = new AtomicReference<>("");
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        IntStream.range(0, 100000).forEach(i -> {
            s.set(s + "i");
        });
        stopWatch.stop();
        System.out.println("String cost:" + stopWatch.getTotalTimeMillis());
    }

    @Test
    public void testStringBuilder() {
        StringBuilder s = new StringBuilder();
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        IntStream.range(0, 100000).forEach(i -> {
            s.append(i);
        });
        stopWatch.stop();
        System.out.println("StringBuilder cost:" + stopWatch.getTotalTimeMillis());
    }

    @Test
    public void testStringBuffer() {

        StringBuffer s = new StringBuffer();
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        IntStream.range(0, 100000).forEach(i -> {
            s.append(i);
        });
        stopWatch.stop();
        System.out.println("StringBuffer cost:" + stopWatch.getTotalTimeMillis());
    }

    @Test
    public void testMultiStringBuilder() throws InterruptedException {
        StringBuilder s = new StringBuilder();
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Thread t1 = new Thread(() -> {
            IntStream.range(0, 100000).forEach(i -> {
                s.append(i);
            });
        });
        Thread t2 = new Thread(() -> {
            IntStream.range(0, 100000).forEach(i -> {
                s.append(i);
            });
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        stopWatch.stop();
        System.out.println("MultiStringBuilder cost:" + stopWatch.getTotalTimeMillis());
    }

    @Test
    public void testMultiStringBuffer() throws InterruptedException {

        StringBuffer s = new StringBuffer();
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Thread t1 = new Thread(() -> {
            IntStream.range(0, 100000).forEach(i -> {
                s.append(i);
            });
        });
        Thread t2 = new Thread(() -> {
            IntStream.range(0, 100000).forEach(i -> {
                s.append(i);
            });
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        stopWatch.stop();
        System.out.println("MultiStringBuffer cost:" + stopWatch.getTotalTimeMillis());
    }

}

应用场景

对于少量的字符串拼接,可以采用String;
对于单线程下大量字符串操作,用StringBuffer和StringBuilder均可;
对于多线程下的大量字符串操作,采用StringBuffer;

上一篇:【车间调度】基于模拟退火算法求解车间调度问题matlab源码


下一篇:【SVM分类】基于人工蜂群算法改进SVM实现数据分类matlab源码