String、stringBuilder和StringBuffer的区别

String类是不可变类,创建对象后,该对象的字符串是不可变的,直到该对象被销毁,但我们平时在用String的时候,String不是可以修改的吗?我们在修改String的字符串时,其实是整个对象都换了,修改后的String对象不再是原来的那个String对象。

String str = "123";
String str2 = str;
System.out.println(str == str2);
str = str + "";
System.out.println(str == str2);

运行结果:

这里==的比较的是对象的指向是否一样。可以看出,修改后String对象的指向发生了变化,这是因为String类的字符串修改的过程中,JVM把之前的那个String对象销毁了,然后又创建了一个新的String对象,对象名是一样的。

而StringBuffer和stringBuilder则是在原来的那个对象上修改。

StringBuilder stringBuilder = new StringBuilder("");
StringBuilder stringBuilder2 = stringBuilder;
System.out.println(stringBuilder == stringBuilder2);
stringBuilder.append("");
System.out.println(stringBuilder == stringBuilder2);

StringBuffer stringBuffer = new StringBuffer("");
StringBuffer stringBuffer2 = stringBuffer;
System.out.println(stringBuffer == stringBuffer2);
stringBuffer.append("");
System.out.println(stringBuffer == stringBuffer2);

运行结果:

 下面我们再看一个示例,来比较这三个类的效率。

final int n = 20000;

long a = System.currentTimeMillis();
String str = "";
for (int i = 0; i < n; i++) {
    str += i;
}
System.out.println("String的运行时间:" + (System.currentTimeMillis()-a)/1000.0 + "s");

long b = System.currentTimeMillis();
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < n; i++) {
    stringBuffer.append(i);
}
System.out.println("StringBuffer的运行时间:" + (System.currentTimeMillis()-b)/1000.0 + "s");

long c = System.currentTimeMillis();
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < n; i++) {
    stringBuilder.append(i);
}
System.out.println("StringBuilder的运行时间:" + (System.currentTimeMillis()-c)/1000.0 + "s");

运行结果:

 由于使用String类在修改数值的时候一直销毁创建,所以它花费的时间比StringBuilder和StringBuffer这两个多得多,而StringBuilder的运行效率比StringBuffer快,那是因为StringBuffer的底层加了synchronized的关键字,用来实现线程安全,因此StringBuilder的运行效率比StringBuffer快。我们用一个示例看一下StringBuffer和StringBuilder的线程安全问题。

StringBuffer:

StringBuffer str = new StringBuffer();
for (int i = 0; i < 100; i++) {
    new Thread(() -> {
        for (int j = 0; j < 1000; j++) {
            str.append("a");
        }
    },String.valueOf(i)).start();
}

try {
    TimeUnit.SECONDS.sleep(1);//等1秒
} catch (InterruptedException e) {
    e.printStackTrace();
}
System.out.println(str.length());

StringBuilder:

StringBuilder str = new StringBuilder();
for (int i = 0; i < 100; i++) {
    new Thread(() -> {
        for (int j = 0; j < 1000; j++) {
            str.append("a");
        }
    },String.valueOf(i)).start();
}

try {
    TimeUnit.SECONDS.sleep(1);//等1秒
} catch (InterruptedException e) {
    e.printStackTrace();
}
System.out.println(str.length());

前面那个返回的结果100000,跟预期的一样。后面返回的结果是94697,跟预期的不一样。这是因为StringBuffer类的append方法加了synchronized的关键字。

总结:

性能上,需要大量修改数值时,StringBuilder最快,StringBuffer次之,String最慢。

单线程下需要对字符串进行大量修改,应优先使用StringBuilder,多线程下需要对字符串进行大量修改,应优先使用StringBuffer,单线程下对字符串修改操作不多时,应优先使用String。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鲤鱼程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值