概要
所有人在学习Java的时候,都被老师强调,字符串相加要用StringBuffer或者StringBuild,表面理解确实会快些,但是经过编译优化后,还会快吗?今天借助Jad反编译工具,看一下优化后,字符串直接相加在不同场景会怎么样。
环境
JDK1.8
IDEA2018.2
jad 1.5.8g
场景
主要分为以下四个场景:
- 简单的直接相加
- 多次相加
- 循环相加
- 有判断的相加
简单相加
源码
public class StringTest {
public static void main(String[] args) {
// String 直接拼接
String a = "1111";
String b = "22222";
String c = "3333";
System.out.println(a + b + c);
}
}
编译后
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: StringTest.java
import java.io.PrintStream;
public class StringTest
{
public StringTest()
{
}
public static void main(String args[])
{
String a = "1111";
String b = "22222";
String c = "3333";
System.out.println((new StringBuilder()).append(a).append(b).append(c).toString());
}
}
多次相加
源码
public class StringTest {
public static void main(String[] args) {
// String 直接拼接
String a = "1111";
String b = "22222";
String c = "3333";
System.out.println(a + b + c);
a = a + b;
System.out.println(a + c);
}
}
编译后
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: StringTest.java
import java.io.PrintStream;
public class StringTest
{
public StringTest()
{
}
public static void main(String args[])
{
String a = "1111";
String b = "22222";
String c = "3333";
System.out.println((new StringBuilder()).append(a).append(b).append(c).toString());
a = (new StringBuilder()).append(a).append(b).toString();
System.out.println((new StringBuilder()).append(a).append(c).toString());
}
}
循环场景
源码
public class StringTest {
public static void main(String[] args) {
String a = "1111";
String b = "22222";
//循环字符串拼接
for (int i = 0; i < 100; i++) {
a = a + b;
}
System.out.println(a);
//循环 buffer拼接
StringBuffer forBuffer = new StringBuffer(a);
for (int i = 0; i < 100; i++) {
forBuffer.append(b);
}
System.out.println(forBuffer.toString());
}
}
编译后
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: StringTest.java
import java.io.PrintStream;
public class StringTest
{
public StringTest()
{
}
public static void main(String args[])
{
String a = "1111";
String b = "22222";
for(int i = 0; i < 100; i++)
a = (new StringBuilder()).append(a).append(b).toString();
System.out.println(a);
StringBuffer forBuffer = new StringBuffer(a);
for(int i = 0; i < 100; i++)
forBuffer.append(b);
System.out.println(forBuffer.toString());
}
}
有判断
源码
public class StringTest {
public static void main(String[] args) {
String a = "1111";
String b = "22222";
int i = 3;
//字符串拼接
if (i % 2 == 0) {
a = a + b;
}
System.out.println(a);
//buffer拼接
StringBuffer forBuffer = new StringBuffer(a);
if (i % 2 == 0) {
forBuffer.append(b);
}
System.out.println(forBuffer.toString());
}
}
编译后
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: StringTest.java
import java.io.PrintStream;
public class StringTest
{
public StringTest()
{
}
public static void main(String args[])
{
String a = "1111";
String b = "22222";
int i = 3;
if(i % 2 == 0)
a = (new StringBuilder()).append(a).append(b).toString();
System.out.println(a);
StringBuffer forBuffer = new StringBuffer(a);
if(i % 2 == 0)
forBuffer.append(b);
System.out.println(forBuffer.toString());
}
}
性能
各种场景下,看到了优化器的结果,那就试试10W字符循环拼接下的,直接相加,Buffer,Builder相加的性能表现。
public class StringTest {
public static void main(String[] args) {
String a = "1111";
String b = "22222";
//循环字符串拼接
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
a = a + b;
}
System.out.println(System.currentTimeMillis() - startTime);
//循环 buffer拼接
StringBuffer forBuffer = new StringBuffer(a);
startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
forBuffer.append(b);
}
System.out.println(System.currentTimeMillis() - startTime);
//循环 buffer拼接
StringBuilder forBuilder = new StringBuilder(a);
startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
forBuilder.append(b);
}
System.out.println(System.currentTimeMillis() - startTime);
}
}
该测试只代表单次结果,如果您的结果与我的不一致,请以您的为准
直接相加:53104ms
Buffer相加:4ms
Builder相加:3ms
结论
在简单字符串拼接中,字符串直接相加,优化器会把代码优化称Builder,无论相加几次,都会只有一个Builder。
在其他拼接场景中,优化器都没有很好的发挥作用,频繁创建Builder对象会严重影响性能。对性能要求较高的项目,可以使用根据线程是否安全自行选择Buffer或者Builder。
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦