小瓜牛漫谈 — String、StringBuffer、StringBuilder

任何一个系统在开发的过程中, 相信都不会缺少对字符串的处理。

在 java 语言中, 用来处理字符串的的类常用的有 3 个:String、StringBuffer、StringBuilder。

它们的异同点:

1) 都是 final 类, 都不允许被继承;

2) String 长度是不可变的, StringBuffer、StringBuilder 长度是可变的;

3) StringBuffer 是线程安全的, StringBuilder 不是线程安全的。

String 类已在上一篇随笔小瓜牛漫谈 — String中叙述过, 这里就不再赘述。本篇随笔意在漫游 StringBuffer 与 StringBuilder。

其实现在网络上谈论 String、StringBuffer、StringBuilder 的文章已经多到不可胜数了。小瓜牛不才, 蜗行牛步, 慢了半个世纪。。。

StringBuilder 与 StringBuffer 支持的所有操作基本上是一致的, 不同的是, StringBuilder 不需要执行同步。同步操作意味着

串联字符串的性能小测:

Application {LOOP_TIMES = 200000;String CONSTANT_STRING = “min-snail”; main(String[] args) { Application().startup(); 9 } testString(){12String string = “”;13long beginTime = System.currentTimeMillis();14for(int i = 0; i < LOOP_TIMES; i++){15string += CONSTANT_STRING;16 }17long endTime = System.currentTimeMillis();18System.out.print(“String : ” + (endTime – beginTime) + “\t”);19 } testStringBuffer(){22StringBuffer buffer = new StringBuffer();23long beginTime = System.currentTimeMillis();24for(int i = 0; i < LOOP_TIMES; i++){25 buffer.append(CONSTANT_STRING);26 }27 buffer.toString();28long endTime = System.currentTimeMillis();29System.out.print(“StringBuffer : ” + (endTime – beginTime) + “\t”);30 } testStringBuilder(){33StringBuilder builder = new StringBuilder();34long beginTime = System.currentTimeMillis();35for(int i = 0; i < LOOP_TIMES; i++){36 builder.append(CONSTANT_STRING);37 }38 builder.toString();39long endTime = System.currentTimeMillis();40System.out.print(“StringBuilder : ” + (endTime – beginTime) + “\t”);41 } startup(){44for(int i = 0; i < 6; i++){45System.out.print(“The ” + i + ” [\t “);46 testString();47 testStringBuffer();48 testStringBuilder();49System.out.println(“]”);50 }51 }52 }

上面示例是频繁的去串联一个比较短的字符串, 然后反复调 6 次。测试是一个很漫长的过程, 在本人的笔记本电脑上总共花去了 23 分钟之多, 下面附上具体数据:

从表格数据可以看出, 使用 String 的 “+” 符号串联字符串的性能差的惊人, 大概会维持在 3分40秒 的时候可以看到一次打印结果;

其次是 StringBuffer, 平均花时 9.2 毫秒; 然后是 StringBuilder, 平均花时 7.5 毫秒。

1) 耗时大的惊人的 String 到底是干嘛去了呢? 调出 cmd 窗口, 敲 jconsole 调出 java 虚拟机监控工具, 查看堆内存的使用情况如下:

实际上这个已经在上一篇 小瓜牛漫谈— String 中提到过, 底层实际上是将循环体内的 string += CONSTANT_STRING; 语句转成了:

string = (new StringBuilder(String.valueOf(string))).append(“min-snail”).toString();

所以在二十万次的串联字符串中, 每一次都先去创建 StringBuilder 对象, 然后再调 append() 方法来完成 String 类的 “+” 操作。

这里的大部分时间都花在了对象的创建上, 而且每个创建出来的对象的生命都不能长久, 朝生夕灭, 因为这些对象创建出来之后没有引用变量来引用它们,

那么它们在使用完成时候就处于一种不可到达状态, java 虚拟机的垃圾回收器(GC)就会不定期的来回收这些垃圾对象。因此会看到上图堆内存中的曲线起伏变化很大。

但如果是遇到如下情况:

在那里,有我们特有的记忆,亲情之忆、

小瓜牛漫谈 — String、StringBuffer、StringBuilder

相关文章:

你感兴趣的文章:

标签云: