zoukankan      html  css  js  c++  java
  • StringBuffer(StringBuilder),不是String更胜String

         String并不是java的基本类型,它是一个对象,但是,创建String是一种“消费行为”(所谓的“消费行为”,就是指该行为是耗时耗内存的行为),而且是一种“误导性的消费行为”,必须防止盲目依赖String,造成不必要的消费。

          对于大多数包括我在内的新手而言,使用String似乎是种理所当然的行为,尤其是学过C++的同学,更是庆幸使用String成为内置支持的行为,即使它不是基本类型。但是,使用String并没有我们表面上那么好,凡是“消费行为”,多少都会存在副作用,而String的副作用是非常容易被忽视的,因为我们甚至不曾去探究过(这就是我说它是“误导性”的原因)!String在java中的真正意义是字符串常量,是一个不可被修改的对象。第一次看到这个的时候,我很惊讶:不是可以进行String的连接,像是这样:
           String str  = "hello";
           str += "word";
    怎么说是不可被修改的呢?仔细研究就会发现一个惊人的事实,str += "word"这个语句已经创建了新的String了!也就是说,之前的str并没有被修改,因为它的引用的地址和str += "word"创建的字符串"hello word"是不同的。在这短短两行语句中就已经创建了两个完全不同的对象,更别提我以前常干的:
          for(int i = 0; i < 10; i++){
               str += "..";
           }
    这简直就是一种灾难!更加可怕的是,我们过去认为应该是同一个String的情况,像是这样:
           String str = "hello";
           str = "word";
    或者:
           changeString(str);
           
            public void changeString(String str){
                  String str = str.replace(...);
             }
    它们其实都是在创建新的String对象,只是我们以前不知道而已。
          没有理解事物的本质就任意的使用,这种行为自古以来就会带来问题。现在,我们已经真正认清楚String的真面目了,是否该开始寻找解决方法呢?就是寻找String的替代品,没有副作用的替代品,StringBuilder和StringBuffer。
           这两者的使用都需要使用new,因为它们是显式的真正对象(String其实也是使用new,只是它是隐式的,我们也可以这样创建String对象:String str = new String("hello"))。它们之间的区别就在于StringBuffer多了一个线程安全性(即同步)的附加好处,方便我们在多线程中安全的使用,其余基本一样,所以,这里单纯只是讨论StringBuffer。
             StringBuffer与String之间不能进行强制类型转化,但是可以互相转化,像是这样:
             String str1 = "hello";
             StringBuffer sb = new StringBuffer(str1);
             String str2 = sb.toString();
    我们使用String,最常用的就是进行+=这样的字符串拼接。StringBuffer的拼接并不像String那样,可以直接使用+,+=,它需要调用方法append(),直接将参数加到字符串的后面,不会产生新的对象。这里要注意,如果是这样:
             String str = "hello" + "word";
             StringBuffer sb = new StringBuffer("hello").append("word");
    使用StringBuffer可能并不会比String快,那是因为在JVM里面,它是这样处理"hello" + "word":一个字符串"hello word",并没有进行+操作,但如果是这样:
              String s1 = "hello";
              String s2 = "word";
              String str = s1 + s2;
    String就会显出原形了!
           StringBuffer更多提供的是对字符串内容的操作,像是插入,反转等等,这些都可以通过文档查看相关使用方法,这里就讲一个我们平时很少注意到的方法:trimToSize(),它会将StringBuffer对象的中存储空间缩小到和字符串一样的长度,减少空间的浪费。
           必须注意的是,StringBuffer的equals()并没有被覆盖,它依然就是Object的equals(),用于比较地址,所以它无法用来进行字符串内容的比较(String就可以)。
            StringBuilder,StringBuffer和String三者间的速度比较如下:
            StringBuilder > StringBuffer > String.
    即使StringBuffer的使用是最安全的,但是大多数情况下是在单线程下使用字符串,不过也不需要担心,因为只有至少百万级别的数量才会体现StringBuilder的速度优势,所以平时这两者爱用谁就用谁。
           如果只是少量的数据,使用String是最方便的,但如果是想要编写一个类的toString()方法,这时就要注意,如果这个方法中对字符串的操作是在循环中,使用StringBuffer是最佳的选择。
            使用StringBuffer时,如果是处理较大的数据,而且可预见一定会超容,请尽量确定StringBuffer的最大容量,因为StringBuffer的构造器创建的是一个默认大小(通常是16)的字符串数组,若超出,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。这种操作在已经拥有一定大小的容量时,是很可怕的,所以,创建时就指定不会被超过的容量,编译器会非常感激你的。
  • 相关阅读:
    宿主机( win 7 系统) ping 虚拟机VMware( cent os 6.6 ) 出现“请求超时”或者“无法访问目标主机”的解决方法
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 21 合并两个有序链表
    Java实现 LeetCode 21 合并两个有序链表
    Java实现 LeetCode 21 合并两个有序链表
  • 原文地址:https://www.cnblogs.com/wenjiang/p/2752702.html
Copyright © 2011-2022 走看看