`
francis.xjl
  • 浏览: 16120 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

关于String累加

阅读更多
昨天在群里跟人讨论关于String累加的问题,貌似没有人能特别准确的知道是一个什么样的情况,今天我通过jclasslib (PS:从http://zangxt.iteye.com/搞到的好东西)来检测一下编译器是如何进行字符串累加的,我们先写一段代码:
package francis;  
public class TestString {  
    public static void main(String[]args) {  
        String s = "";  
        for(int i = 0; i < 1000; i++) {  
            s += i;  
        }  
        System.out.println(s);  
    }  
}  

很简单,貌似网上也能给出一个大概的结论,但是我们还是亲手看一下编译后的代码:

我们可以看到上面的程序被编译成了22行的代码,我们注意看一下第6行到第18行,这是整个for循环所执行的代码,我们会很明显的看到,每次循环都会执行第6行的代码,也就是每次都会新建了一个StringBuilder对象,这多么浪费性能啊。

这就很明显了,每一次字符串的拼接,编译器都是通过新建StringBuilder对象来完成的。

哎,如果编译器足够智能,将新建StringBuilder对象放到循环之外,就不用我们去操心性能问题,但是,貌似目前编译器还办不到。所以我们手动的新建StringBuilder是比较好的方案:
package francis;  
public class TestString {  
    public static void main(String[]args) {  
        String s = "";  
        StringBuilder sb = new StringBuilder(s);  
        for(int i = 0; i < 1000; i++) {  
            sb.append(i);  
        }  
        s = sb.toString();  
        System.out.println(s);  
    }  
}  

为了确定是否真的达到效果,我们来看一下这次编译后的代码:

这次循环的代码是在11~18行,而创建StringBuilder对象是在第三步执行。这样就避免了编译器会每个循环都新建一个StringBuilder对象了。比较好的习惯就是当连接字符串操作比较多的时候直接手动新建StringBuilder对象.

那有人可能会问了,String的每次拼接都是利用创建StringBilder对象来处理么? 实践乃检验真理的唯一方法:

先写代码:
package francis;  
public class TestString {  
    public static void main(String[]args) {  
        String a = "a" + "b" + "c";  
        String b = a + "b";  
        String c = a + b;  
        System.out.println(a + b + c);  
    }  
} 

然后再看一下编译后的结果,由于比较长,我分成两张图片:


很显然,有四个new StringBuilder操作。基本可以得出结论:需要字符串连接的时候,如果没有可用的对应的StringBuilder就会去新建。因此字符串操作还是推荐自己手动去new StringBuilder,不能依赖编译器的优化。

当然会有很多其它情况,比如我在第三行代码后面加一个c+=a;a+=b;会产生什么样的情况呢?实践乃检验真理的唯一方法,自己去检测吧~~
分享到:
评论

相关推荐

    Spark的广播变量和累加器使用方法代码示例

    一、广播变量和累加器 通常情况下,当向Spark操作(如map,reduce)传递一个函数时,它会在一个远程集群节点上执行,它会使用函数中所有变量的副本。这些变量被复制到所有的机器上,远程机器上并没有被更新的变量会向...

    java 经典习题.doc

    public static void main(String[] args) { int t = 0; for (int i = 1; i ; i++) { t = i + 100; for (int j = 1; j ; j++) { if (t == j * j) { t = t + 168; for (int p = 1; p ; p++) ...

    Spark代码笔记03——自定义排序、自定义分区、累加器、广播变量

    一、自定义排序 自定义排序  Spark对简单的数据类型可以直接排序,但是对于一些复杂的条件就需要...case class Girl(name:String,faceValue:Int,age:Int) object myOrder{ implicit val girlOrdering=new Ordering[Gi

    base37-string:将字符串哈希为64位数字

    将累加器acc初始化为0 遍历c[]以获取单个字符代码c : 如果65 &lt;= c &lt;= 90 ,则让i等于(1 + c) - 65 如果97 &lt;= c &lt;= 122 ,则让i等于(1 + c) - 97 如果48 &lt;= c &lt;= 57 ,则让i等于(27 + c) - 48...

    C# 利用StringBuilder提升字符串拼接性能的小例子

    此函数中遍列所有数据行,通过Replace替换标签生成Excel行,然后将行数据累加赋值到一个字符串 代码如下:string excelString = “”; foreach(var item in list){ excelString += string.Format(“….{0}”,list....

    汇编速查手册

    CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX ) XADD 先交换再累加.( 结果在第一个操作数里 ) XLAT 字节查表转换. ── BX 指向一张 256 字节的表的起点, AL 为表的索引值 (0-255,即 0-FFH); 返回...

    编写一个类实现银行帐户的概念

    编写一个类实现银行帐户的概念,包括的属性有“帐号”、“储户姓名”、“地址”、“存款余额”,包括的方法有“存款”、“取款”、“查询”、“计算利息”、“累加利息”等。 二、实验要求 1) 改写上面的类,增加...

    校验和算法

    #include &lt;string.h&gt; #define MAX_BUFF 256 void main(int argc,char* argv[]) { FILE* stream; char buff[MAX_BUFF]; //缓冲区数组 最大256个字符 long sum=0; //累加器 char nstring[5]; //待转换成数字进行...

    Java中 List《map》把里面map中某个key相同记录的其他key 的 value 合并

    Java中 List《map》把里面map中某个key相同记录的其他key 的 value 合并 Java中 List《map》把里面map中某个key相同记录的其他key 的 value 合并

    solidity入门学习——mapping

    一、solidity中,映射的关键字为mapping,首先我们先来定义两个mapping, mapping(address =&gt;uint) idmapping和mapping(uint =&gt;string) namemapping。idmapping用来表示地址变量和整型变量的对应关系,在注册过程中...

    汉字转拼音缩写示例代码(Silverlight和.NET 将汉字转换成为拼音)

    代码如下:/// &lt;summary&gt; /// 汉字转拼音缩写 /// &lt;/summary&gt; /// ”str”&gt;要转换的汉字字符串&lt;/param&gt; /// 拼音缩写&lt;/returns&gt; public string GetPYString(string str) { string tempStr = “”; foreach(char c in ...

    序列号生成器

    //如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加 } lastTimestamp = timestamp; long suffix = (datacenterId ) | (workerId ) | sequence; String datePrefix = ...

    cad-VBA绘图简易程序

    pm1 = "选择所有累加的数:" pm2 = "选择所有加数:" Case "2" pm1 = "选择所有被减数:" pm2 = "选择所有减数:" Case "3" pm1 = "选择所有累乘数:" pm2 = "选择所有乘数:" Case "4" pm1 = "选择所有被除数:" pm...

    2014最新QQWry.Dat 下载

    private static string IntToIP(long ip_Int) { long num = (long) ((ip_Int & 0xff000000L) &gt;&gt; 0x18); if (num ) { num += 0x100L; } long num2 = (ip_Int & 0xff0000L) &gt;&gt; 0x10; if (num2 ) { num2 += ...

    C# 黑马.Net_大文件拷贝实例源码

    大文件拷贝实例源码,学习关于IO文件流、多线程相关使用做参考。 private void button4_Click(object sender, EventArgs e) { this.progressBar1.Value = 0; this.label1.Text = "0%"; if (!File.Exists(this....

    IO输入输出留

    public static void main(String[] args) throws IOException { test4(); } //创建临时文件 文件名称不能太短 private static void test4() throws IOException { File f = File.createTempFile("abc", "....

    Spring-redis-redission.zip

    Spring boot整合分布式缓存Redis,包含redission对分布式数据结构list,string,hashmap,zset,set和对象的读写实例 包含一个redission的分布式可重入锁RLock使用实例 分布式对象:地理空间对象、分布式累加器。

    香农编码实验报告(1).doc

    3、由大到小重新排列信源 4、实现信源概率的叠加 5、计算码长l 6、编码 7、计算平均码长pl、信源熵Hx以及编码效率q 三、源程序: #include&lt;iostream&gt; #include&lt;math.h&gt; #include&lt;string&gt; using namespace std;...

    C++实现大数相乘的算法

    由于数字无法用一个整形变量存储,很自然的想到...为了节约空间,所有的中间结果直接在m+n的辅存上进行累加。 C++实现大数相乘代码如下: #include #include&lt;string&gt; using namespace std; string BigNumMultiply(str

    汇编指令 中文对照

    至少有一個操作數為寄存器,段寄存器不可作為操作數) CMPXCHG比較並交換操作數.( 第二個操作數必須為累加器AL/AX/EAX ) XADD 先交換再累加.( 結果在第一個操作數裡 ) XLAT (TRANSLATE) 字節查表轉換. &lt;br...

Global site tag (gtag.js) - Google Analytics