注册
 找回密码
 注册
江西广告网
查看: 330|回复: 0
打印 上一主题 下一主题

Java堆和栈与StringBuilder效率探究

[复制链接]

该用户从未签到

1
跳转到指定楼层
发表于 2009-1-14 08:27:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册

x
对象的创建(即内存的分配 ) 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变量引用。 [1] [2] [3] 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); 上一页 [1] [2] [3] 创建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 上一页 [1] [2] [3]
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表