当前位置: 首页 > 图灵资讯 > 技术篇> String、StringBuffer和StringBuilder

String、StringBuffer和StringBuilder

来源:图灵教育
时间:2023-05-19 09:07:54

Stringbuffer用于写json类,关于它的特点和String、Stringbuffer之间的一些差异,在网上有更多的见解,以下是一篇写得更好的文章: 相信大家对 String 和 StringBuffer 已经很清楚了,但估计还是会有很多同志对这两类的工作原理有些不清楚的地方,今天我在这里再给大家复习一下这个概念,顺便把它拉出来 J2SE 5.0 一个新的字符操作类别—— StringBuilder (不要忙着扔我的砖,我还清醒,我在这里说的不是 C #, Java 也有 StringBuilder 类)。那么这个 StringBuilder 和 StringBuffer 我们第一次见面 String 类有什么区别?那么这个 StringBuilder 和 StringBuffer 我们第一次见面 String 有什么区别?我们应该在不同的场合使用哪一种?我想谈谈我对这些类别的看法。我也希望你能提出意见。每个人都有错误,这是一个学习错误和改变的好机会。 简要的说, String 类型和 StringBuffer 实际上,类型的主要性能差异在于 String 是不可改变的对象(为什么?问问 Java 设计师,为什么? String 不是原生类型吗?)所以每次都是对的 String 改变类型实际上相当于生成一个新的 String 对象,然后指向新的指针 String 因此,最好不要使用经常改变内容的字符串 String ,因为每个生成对象都会影响系统的性能,特别是当内存中没有引用的对象较多时, JVM 的 GC 我会开始工作,速度肯定会很慢。试着举一个不太合适的例子:

String S1 = “abc”; For(int I = 0 ; I < 10000 ; I ++) // For 多次调用模拟程序 { S1 + = “def”; S1 = “abc”; }

如果是这样的话,到此为止 for 循环结束后,如果内存中的对象没有被记录下来 GC 如果清理干净,内存共有 2 有一万多个惊人的数字,如果这是一个很多人使用的系统,这样的数字就不多了,所以我们在使用它时必须小心。 如果是用的话 StringBuffer 类则结果不同,每次结果都是正确的 StringBuffer 对象本身进行操作,而不是生成新的对象,然后改变对象引用。因此,在正常情况下,我们推荐它 StringBuffer ,特别是当字符串对象经常发生变化时。在某些特殊情况下, String 实际上,物体的字符串拼接是由物体的字符串拼接而成的 JVM 解释成了 StringBuffer 物体的拼接,所以这些时候 String 对象的速度不会比 StringBuffer 对象较慢,特别是在生成以下字符串对象时, String 效率远远高于 StringBuffer 快的:

String S1 = “This is only a” + “ simple” + “ test”; StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

你会惊讶地发现,生成 String S1 对象的速度太快了,这个时候 StringBuffer 出乎意料的是,速度根本没有优势。其实这是 JVM 一个把戏 JVM 眼里,这个 String S1 = “This is only a” + “ simple” + “test”; 其实就是: String S1 = “This is only a simple test”; 所以当然不需要太多时间。但是这里要注意的是,如果你的字符串来自另一个字符串 String 对象来说,速度就没那么快了,比如:

String S2 = “This is only a”; String S3 = “ simple”; String S4 = “ test”; String S1 = S2 +S3 + S4;

这时候 JVM 按照原来的方式会规规矩矩地做, S1 对象的生成速度不像刚才那么快,我们可以在一段时间内进行测试来验证。 因此,我们得出第一步的结论: 在大多数情况下 StringBuffer > String 而 StringBuilder 和他们比较怎么样?先简单介绍一下, StringBuilder 是 JDK5.0 中新增加的一个类别,它跟随 StringBuffer 区别取决于下面的介绍 Java.lang.StringBuffer 可变字符序列线程安全。类似于 String 字符串缓冲区,但不能修改。多线程可安全使用字符串缓冲区。必要时可以同步这些方法,所以任何特定实例中的所有操作似乎都是按串行顺序进行的,这与所涉及的每个线程的调用顺序一致。 每个字符串缓冲区都有一定的容量。只要字符串缓冲区中包含的字符序列长度不超过此容量,就不需要分配新的内部缓冲区数组。如果内部缓冲区溢出,容量会自动增加。从 JDK 5.0 一开始,单线程使用的等价类被添加到这一类中,即 StringBuilder 。与此类相比,通常应优先使用 StringBuilder 类,因为它支持所有相同的操作,但因为它不同步,所以速度更快。 但是如果将 StringBuilder 多线程使用的实例是不安全的。建议使用此类同步 StringBuffer 。 据估计,每个人都能理解它们之间的区别,所以让我们做一个一般的推导: 在大多数情况下 StringBuilder > StringBuffer 因此,根据这种不等式的传输定理: 在大多数情况下 StringBuilder > StringBuffer > String 既然有这样的推导结果,我们就做一个测试验证: 测试代码如下:

public class testssb { /** Creates a new instance of testssb */ final static int ttime = 10000;// 测试循环次数 public testssb() { } public void test(String s){ long begin = System.currentTimeMillis(); for(int i=0;i<ttime;i++){ s += "add"; } long over = System.currentTimeMillis(); System.out.println(" 操作 "+s.getClass().getName()+" 使用类型的时间为: " + (over - begin) + " 毫秒 " ); } public void test(StringBuffer s){ long begin = System.currentTimeMillis(); for(int i=0;i<ttime;i++){ s.append("add"); } long over = System.currentTimeMillis(); System.out.println(" 操作 "+s.getClass().getName()+" 使用类型的时间为: " + (over - begin) + " 毫秒 " ); } public void test(StringBuilder s){ long begin = System.currentTimeMillis(); for(int i=0;i<ttime;i++){ s.append("add"); } long over = System.currentTimeMillis(); System.out.println(" 操作 "+s.getClass().getName()+" 使用类型的时间为: " + (over - begin) + " 毫秒 " ); } // 对 String 直接测试字符串拼接 public void test2(){ String s2 = "abadf"; long begin = System.currentTimeMillis(); for(int i=0;i<ttime;i++){ String s = s2 + s2 + s2 ; } long over = System.currentTimeMillis(); System.out.println(" 操作字符串对象引用相加使用类型的时间为: " + (over - begin) + " 毫秒 " ); } public void test3(){ long begin = System.currentTimeMillis(); for(int i=0;i<ttime;i++){ String s = "abadf" + "abadf" + "abadf" ; } long over = System.currentTimeMillis(); System.out.println(" 操作字符串的相加使用时间为: "+ (over - begin) + " 毫秒 " ); } public static void main(String[] args){ String s1 ="abc"; StringBuffer sb1 = new StringBuffer("abc"); StringBuilder sb2 = new StringBuilder("abc"); testssb t = new testssb(); t.test(s1); t.test(sb1); t.test(sb2); t.test2(); t.test3(); } }

以上代码在 NetBeans 5.0 IDE/JDK1.6 通过上面的编译,循环次数 ttime 为 10000 二次试验结果如下: 操作 java.lang.String 使用类型的时间为: 4392 毫秒 操作 java.lang.StringBuffer 使用类型的时间为: 0 毫秒 操作 java.lang.StringBuilder 使用类型的时间为: 0 毫秒 操作字符串对象引用相加使用类型的时间为: 15 毫秒 操作字符串的相加使用时间为: 0 毫秒 好像还是看不见 StringBuffer 和 StringBuilder 的区别,把 ttime 加到 30000 次看看: 操作 java.lang.String 使用类型的时间为: 53444 毫秒 操作 java.lang.StringBuffer 使用类型的时间为: 15 毫秒 操作 java.lang.StringBuilder 使用类型的时间为: 15 毫秒 操作字符串对象引用相加使用类型的时间为: 31 毫秒 操作字符串的相加使用时间为: 0 毫秒 StringBuffer 和 StringBuilder 的性能还是没有太大的区别,再加大到 100000 看,这里就不加对了。 String 类型测试,因为对 String 这么大数据量的测试类型会很慢... 操作 java.lang.StringBuffer 使用类型的时间为: 31 毫秒 操作 java.lang.StringBuilder 使用类型的时间为: 16 毫秒 可以看出差异,然而,许多测试结果实际上是 StringBuffer 比 StringBuilder 快点,再加一点 1000000 看(应该不会当机吧?): 操作 java.lang.StringBuffer 使用类型的时间为: 265 毫秒 操作 java.lang.StringBuilder 使用类型的时间为: 219 毫秒 差别很小,结果很稳定,再大一点看, ttime = 5000000 : ······ Exception in thread "main" java.lang.OutOfMemoryError: Java heap space ······ 呵呵,算了吧,不要去测试,基本上就是性能而言 StringBuilder > StringBuffer > String 的了。