【转】String字符串相加的问题
前几天同事跟我说我之前写的代码中在操作字符串时候,使用字符串相加的方式而不是使用StringBuffer或者StringBuilder导致内存开销很大。这个问题一直在困扰我,因为在《Think in java》一书中,作者说使用“+”拼接字符串并不比StringBuffer或者StringBuilder效率低下,因为“+”是java唯一一个系统级的针对字符串的重载过的操作符。
大家都知道String是一个final修饰的类。那么两个字符串使用“+”相加到底会不会导致字符串操作效率受到影响呢?
下面是书中和牛人的理解的结合:
用bytecode来说明问题:
1.使用String + 的方式:
public class Test2 {
public static void main(String[] args) {
String a = "a";
String b = "b";
String c = "c";
String s = a + b + c;
}
}
【同时揭示了为何变量相加时 与常量池中的“abc”不相等 因为相加变量本质上是一个StringBuilder对象】
对应的bytecode为:
public class Test2 extends java.lang.Object{
public Test2();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String a
2: astore_1
3: ldc #3; //String b
5: astore_2
6: ldc #4; //String c
8: astore_3
9: new #5; //class StringBuffer
12: dup
13: invokespecial #6; //Method java/lang/StringBuffer."<init>":()V
16: aload_1
17: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
20: aload_2
21: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
24: aload_3
25: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
28: invokevirtual #8; //Method java/lang/StringBuffer.toString:()Ljava/lan
g/String;
31: astore 4
33: return
}
2.使用StringBuffer.append()的方式:
public class Test3 {
public static void main(String[] args) {
String a = "a";
String b = "b";
String c = "c";
StringBuffer sb = new StringBuffer();
sb.append(a).append(b).append(c);
String s = sb.toString();
}
}
对应的bytecode为:
public class Test3 extends java.lang.Object{
public Test3();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String a
2: astore_1
3: ldc #3; //String b
5: astore_2
6: ldc #4; //String c
8: astore_3
9: new #5; //class StringBuffer
12: dup
13: invokespecial #6; //Method java/lang/StringBuffer."<init>":()V
16: astore 4
18: aload 4
20: aload_1
21: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
24: aload_2
25: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
28: aload_3
29: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
32: pop
33: aload 4
35: invokevirtual #8; //Method java/lang/StringBuffer.toString:()Ljava/lan
g/String;
38: astore 5
40: return
}
看到了么?后者不光不比前者效率高,反而多了一些临时变量的存取
至于推荐用StringBuffer来代替String+拼装字符串,说的是循环方式下,如:
public class Test4 {
public static void main(String[] args) {
String s = "s";
for (int i = 0; i < 20; i++) {
s += i;
}
}
}
对应的bytecode为:
public class Test4 extends java.lang.Object{
public Test4();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String s
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: bipush 20
8: if_icmpge 36
11: new #3; //class StringBuffer
14: dup
15: invokespecial #4; //Method java/lang/StringBuffer."<init>":()V
18: aload_1
19: invokevirtual #5; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
22: iload_2
23: invokevirtual #6; //Method java/lang/StringBuffer.append:(I)Ljava/lang
/StringBuffer;
26: invokevirtual #7; //Method java/lang/StringBuffer.toString:()Ljava/lan
g/String;
29: astore_1
30: iinc 2, 1
33: goto 5
36: return
}
如果用String+的方式,每循环一次,就会重新new一个StringBuffer对象,这样的内存消耗完全是不必要的(在数据量大的情况下,还会导致内存不足的错误),所以要这样做:
public class Test5 {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("s");
for (int i = 0; i < 20; i++) {
sb.append(i);
}
}
}
这样无论循环多少次,都只会生成一个StringBuffer对象
回想下代码,我确实是在循环中使用了“+”,而且循环次数还不少,同事说的没错,改为StringBuffer就快多了。特此记下。
【转】String字符串相加的问题的更多相关文章
- String 字符串相加比较
String 字符串相加 对比 public static void main(String[] args) { String a = "helloword"; final Str ...
- String字符串相加的原理
因为String是非常常用的类, jvm对其进行了优化, jdk7之前jvm维护了很多的字符串常量在方法去的常量池中, jdk后常量池迁移到了堆中 方法区是一个运行时JVM管理的内存区域,是一个线程共 ...
- String字符串相加常见面试题
String name1="jack"; String name2="jack"; System.out.println(name1==name2); // t ...
- C语言关于利用sscanf实现字符串相加减
#include<stdio.h>#include<string.h>void main(){ int a; int b; char str1[10] = "9999 ...
- java中String字符串的==解析
今天不知道怎么看了下string的==的问题,本身我觉得我这个水平去判断几个字符串相等还能出问题?呵呵,真的出了大问题,根本原因在于对java字节码的不了解. 首先,==运算符比较的是两个变量所指向的 ...
- 代码题(59)— 字符串相加、字符串相乘、打印最大n位数
1.415. 字符串相加 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和. 思路:和链表相加类似,求进位. class Solution { public: string addS ...
- Java中String字符串toString()、String.valueOf()、String强转、+ ""的区别
Object#toString(): Object object = getObject(); System.out.println(object.toString()); 在这种使用方法中,因为ja ...
- LeetCode:字符串相加【415】
LeetCode:字符串相加[415] 题目描述 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和. 注意: num1 和num2 的长度都小于 5100.num1 和num2 都只 ...
- String字符串性能优化的几种方案
String字符串是系统里最常用的类型之一,在系统中占据了很大的内存,因此,高效地使用字符串,对系统的性能有较好的提升. 针对字符串的优化,我在工作与学习过程总结了以下三种方案作分享: 一.优化构建的 ...
随机推荐
- 关于request、response转发与重定向的简述
在做页面的请求与响应的时候我们多用request与response进行操作,而我们大家也知道,request是表示用户发向服务器的请求,而response是对用户请求的一个响应. 关于转发和重定向,通 ...
- 简单易上手的Bootstrap
什么是Bootstrap? Bootstrap是一个web框架.Bootstrap,来自 Twitter,是目前很受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT ...
- python注释方法以及编码问题
一.单行注释 在python中常使用"#"来进行单行注释,其快捷键为"ctrl+/",如果要对多行代码也就是代码块进行注释时,也可以选中多行按下 "c ...
- JQ在线引用地址
1.7.2版本 百度的引用地址: <script src="http://libs.baidu.com/jquery/1.7.2/jquery.min.js">< ...
- 团队作业4——第一次项目冲刺 SiStH DaY
项目冲刺--??? 你以为penta kill以后就没事了嘛,就没得写了吗?你还期待我会给你一个六杀?七杀?别逗了,你以为你玩三国杀呢,做项目这么严肃的事情,怎么能玩笑. 那么我就在这里明明白白地告诉 ...
- 1st 四则运算题目生成程序
程序代码见此 程序展示 需求分析 需要程序能根据用户指定生成四则运算的题目,并且能让用户做题,并且最后打分统计正确率 功能设计 主要实现的功能就是: 接受用户输入以便知道要出多少道题目(-n x) 能 ...
- 201521123017 《Java程序设计》第9周学习总结
1. 本周学习总结 2. 书面作业 Q1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避免? 1.3 什么样的 ...
- 201521123039 《java程序设计》第九周学习总结
1. 本周学习总结 2. 书面作业 本次PTA作业题集异常 常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避免? ...
- 201521123053《Java课程设计》第十四周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 知识点: 创建表的命令有若干行,如果中间某行输入错误,不能修改:可以使用记事本现将命令输入,然后复制粘贴到mys ...
- lintcode.22 平面列表
平面列表 描述 笔记 数据 评测 给定一个列表,该列表中的每个要素要么是个列表,要么是整数.将其变成一个只包含整数的简单列表. 注意事项 如果给定的列表中的要素本身也是一个列表,那么它也可以包含 ...