频 道 直 达 - 新闻 - 读书 - 培训 - 教程 - 前沿 - 组网 - 系统应用 - 安全 - 编程 - 存储 - 操作系统 - 数据库 - 服务器 - 专题 - 产品 - 案例库 - 技术圈 - 博客 - BBS
51CTO.COM_中国领先的IT技术网站
找资料:

Java堆和栈与StringBuilder效率探究

作者: Administrator 出处:Java家 2008-05-08 17:20    砖    好    评论   进入论坛
阅读提示:Java中的数据类型有两种。基本类型(primitive types), 共有8种,即int, short, long, byte, float, double, boolean, char。存在于栈中。另一种是包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中。

对象的创建(即内存的分配 )

Thinking in Java中详细介绍了当程序运行的时候,具体的内存分配。

可以分为寄存器、堆栈、堆、常量存储、非RAM存储。

下面具体分析一下java中的堆和栈

1、两者比较

1). 栈(stack)与堆(heap)都是Java用来在RAM中存放数据的地方。

栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共 享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要 在运行时动态分配内存,存取速度较慢。

2). Java中的数据类型有两种。基本类型(primitive types), 共有8种,即int, short, long, byte, float, double, boolean, char。存在于栈中。另一种是包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中.

2、String处理

String str = "abc";和String str = new String("abc");和char[] c = {'a','b','c'};String str=new String(c);都采用堆存储

String str = "abc";在栈中如果没有存放值为"abc"的地址,等同于:
String temp=new String("abc");
String str=temp;

1). 关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:先定义一个名为str的对String类的对象引用变量:String str;

2). 在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象o,并将o的字符 串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为"abc"的地址,则查找对象o,并返回o的地址。

3). 将str指向对象o的地址。

使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。

char[] c = {'a','b','c'};String str=new String(c);
等同于

String str = new String('a'+'b'+'c'); 

1、

class Test {
public static void main(String[] args) {
String s = "123";
}

}


Runtime Heap Summary: Test
==========================

Runtime Instance List
---------------------

Packag    Class              Count      Cumulative     Count      Memory  Cumulative     Memory

Total                2 (100.0%)       2 (100.0%)        48 (100.0%)       48 (100.0%)
String      1  (50.0%)       1  (50.0%)        24  (50.0%)       24  (50.0%)
char[ ]      1  (50.0%)       1  (50.0%)       24  (50.0%)       24  (50.0%)

 

结论:String s = "123",会创建一个"123"字符数组和一个String对象。

2、

class Test {
public static void main(String[] args) {
String s = new String("123");

}

}


Runtime Heap Summary: Test
==========================

Runtime Instance List
---------------------

Package      Class       Count       Cumulative Count      Memory       Cumulative Memory
-------      -----       -----       ----------------      ------       -----------------
Total      3 (100.0%)       3 (100.0%)       72 (100.0%)       72 (100.0%)
java.lang    String     2  (66.7%)       2  (66.7%)       48  (66.7%)       48  (66.7%)
char[ ]    1  (33.3%)       1  (33.3%)       24  (33.3%)       24  (33.3%)

结论:String s = new String("123");根据上面的测试可以看出,"123"创建了一个数组,一个String对象,而new String()又根据"123"对象作为参数,重新生成了一个新的String对象,此对象被s变量引用。

3、

class Test {
public static void main(String[] args) {
String s1 = "123";
String s2 = "123";
if (s1 == s2) {
System.out.println("s1==s2");
} else {
System.out.println("s1!=s2");
}
}
}


输出结果:s1==s2


4、

class Test {
public static void main(String[] args) {
String s1 = new String("123");
String s2 = new String("123");
if (s1 == s2) {
System.out.println("s1==s2");
} else {
System.out.println("s1!=s2");
}
}
}


结果:s1!=s2

 
5、

class Test {
public static void main(String[] args) {
String s1 = new String("123");
String s2 = new String("123");
}

}

Runtime Heap Summary: Test
==========================

Runtime Instance List
---------------------

Package      Class       Count       Cumulative Count      Memory       Cumulative Memory
-------      -----       -----       ----------------      ------       -----------------
Total      4 (100.0%)       4 (100.0%)       96 (100.0%)       96 (100.0%)
java.lang    String     3  (75.0%)       3  (75.0%)       72  (75.0%)       72  (75.0%)
char[ ]    1  (25.0%)       1  (25.0%)       24  (25.0%)       24  (25.0%)

结论:相同字符串常量,即使在不同语句中被引用,其内存是共用的,"123"只生成一个字符数据和一个String对象,两个new String()分别生成了一个对象。

6、

class Test
{
public static void main(String[] args)
{
String s1 = new String("123");
String s2 = new String("1234");
}
}

Runtime Heap Summary: Test
==========================

Runtime Instance List
---------------------

Package      Class       Count       Cumulative Count       Memory       Cumulative Memory
-------      -----       -----       ----------------       ------       -----------------
Total       6 (100.0%)       6 (100.0%)       144 (100.0%)      144 (100.0%)
java.lang     String     4  (66.7%)       4  (66.7%)        96  (66.7%)       96  (66.7%)
char[ ]    2  (33.3%)       2  (33.3%)        48  (33.3%)       48  (33.3%)



结论:"123"和"1234"分别生成了各自的字符数组和String对象。两个new String()分别创建一个String对象。

做了一个测试,

long begin = System.nanoTime();              

//String str = "abcdefghijklmnopqrstuvwxyz";

String str1 = new String("abcdefghijklmnopqrstuvwxyz");               

long end = System.nanoTime();              

System.out.println(end - begin);


创建str对象的时间是: 6426纳秒,创建str1的时间是:29334纳秒。

采用new String()方式比直接赋值,效率上比第一个慢5~10倍(视机器配置)。从而验证了上面的结论。

字符串连接效率比较

/**

* 验证 + 和 StringBuffer还有StringBuilder的效率

*/

int count = 50;

String s = "t";

long begin = System.nanoTime();

for (int i = 0; i < count; i++) {

s += "t"+i;

}

long end = System.nanoTime();

System.out.println(end - begin);

StringBuffer sb = new StringBuffer();

begin = System.nanoTime();

for (int i = 0; i < count; i++) {

sb.append("t"+i);

}

end = System.nanoTime();

System.out.println(end - begin);

StringBuilder sbuild = new StringBuilder();

begin = System.nanoTime();

for (int i = 0; i < count; i++) {

sbuild.append("t"+i);

}

end = System.nanoTime();

System.out.println(end - begin);
/* Output:

233828
131022
120686 

可以看到当每次连接的字符串不一样的时候,StringBuilder的效率最高,而+操作的效率最低,

如果每次连接的字符串相同的话,也是+操作最耗时。

/**

* 验证 + 和 StringBuffer还有StringBuilder的效率

*/

int count = 20;

String s = "test";

long begin = System.nanoTime();

for (int i = 0; i < count; i++) {

s += "test";

}

long end = System.nanoTime();

System.out.println(end - begin);

StringBuffer sb = new StringBuffer();

begin = System.nanoTime();

for (int i = 0; i < count; i++) {

sb.append("test");

}

end = System.nanoTime();

System.out.println(end - begin);

StringBuilder sbuild = new StringBuilder();

begin = System.nanoTime();

for (int i = 0; i < count; i++) {

sbuild.append("test");

}

end = System.nanoTime();

System.out.println(end - begin);

/* Output:

116495
20394
19276

【相关文章】

【责任编辑:碧海蓝天 TEL:(010)68476606】

专题
Java实用开发全集
Java类的基础教程专题
Java发展动态专题
Java编程开发手册
Java基础教程
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 领 先 的 IT 技 术 网 站 ·
技 术 成 就 梦 想
·Java基础教程 (查看76818次)
·UML类图详解 (查看67664次)
·C++是垃圾语言?! (查看37165次)
·UML统一建模语言 (查看36784次)
·C#技术开发指南 (查看36765次)
·Java编程开发手册 (1196个砖)
·Java基础教程 (430个砖)
·C#技术开发指南 (311个砖)
·.NET开发手册 (245个砖)
·PB开发教程 (223个砖)
·Java编程开发手册 (657个好)
·Java基础教程 (577个好)
·.NET开发手册 (276个好)
·PB开发教程 (212个好)
·Delphi开发技术手册 (197个好)
订阅技术快讯
电子杂志下载
名称:SQL Server数据库管理精品黄皮书
简介:书中文章经过精挑细选,便于用户能根据自己的实际工作和学习,快速在本书寻找到相关资料。内容涵盖了SQL Server的安装与升级、语句查询、数据备份和恢复、自动化任务、数据同步、数据字典、安全和预防、性能和优化、集群等各方面应用信息,以及DBA管理人员在数据库管理工作中
名称:2007路由技术大全
简介:《2007路由技术大全》由51CTO.com网站特别策划制作,该书包括路由器技术、路由器产品、路由器配置、安全设置、路由器故障处理、路由器密码恢复,以及广大网友在实践使用中的心得经验和技巧文章,内容注重实用性,适用于初学者入门,也适合多年从业者提高,是一本实践和理论完
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。
网络故障排除宝典
网络故障排除宝典
Vista SP1对决XP SP3
Vista SP1对决XP ..
华为路由器配置
华为路由器配置
· 华为路由器配置
· 2008年上半年全国软考..
· AIX操作系统管理应用(..
· 微软出价446亿美元收购..
· 华为员工自杀频频拷问..
· 三层交换技术专题
· ARP攻击防范与解决方案
· 隐私保护技术探讨
· 反垃圾邮件技术应用
· 龙芯要做中国的“奔腾”
· Windows Server 2008专..
· AMD Phenom三核处理器..
· 路由器设置与口令恢复
· 微软Forefront企业安全..
· LAMP技术精解
· 企业数据恢复指南
ARP攻击防范与解决方案
ARP攻击防范与解..
iSCSI应用与发展
iSCSI应用与发展
SQL Server 2008/2005全解
SQL Server 2008/..
· SQL Server 2008/2005..
· SOA 面向服务架构
· SQL Server 2008/2005..
· iSCSI应用与发展
· RAID——磁盘阵列基础
· Apache技术专题
· 中间件应用技术专题
· 三层交换技术专题
· SQL Server入门到精通
· Apache技术专题
· 国际文档格式标准开战
· 路由器设置与口令恢复
· 打造安全服务器
· PHP开发应用手册
· SOA 面向服务架构
· 企业数据恢复指南
ARP攻击防范与解决方案
ARP攻击防范与解..
SQL Server 2008/2005全解
SQL Server 2008/..
iSCSI应用与发展
iSCSI应用与发展
· iSCSI应用与发展
· 中间件应用技术专题
· SQL Server入门到精通
· SQL Server 2008/2005..
· SOA 面向服务架构
· Apache技术专题
· iSCSI应用与发展
· 三层交换技术专题
· Apache技术专题
· 企业数据恢复指南
· RAID——磁盘阵列基础
· 路由器设置与口令恢复
· SOA 面向服务架构
· ADSL应用面面俱到
· ADSL应用面面俱到
· 反垃圾邮件技术应用