字符串操做是编写程序中最多见的行为,本文对String、StringBuilder、StringBuffer三个类在字符串处理方面的效率进行分析。
Java中最多见也是应用最普遍的类就是String类。
- String:Strings are constant; their values cannot be changed after they are created.
这是JDK对String的解释,意思是:String是常量,一旦建立后它的值不能被修改。
先看String对象是如何建立的:
- String str1 = “abc”;
- String str2 = new String(“abc”);
这是咱们常见的两种形式。
第一种方式建立的字符串会放在栈里,更确切的是常量池中,常量池就是用来保存在编译阶段肯定好了大小的数据,通常咱们定义的int等基本数据类型就保存在这里。其具体的一个流程就是,编译器首先检查常量池,看看有没有一个“abc”,若是没有则建立。若是有的话,则则直接把str1指向那个位置。
第二种建立字符串的方法是经过new关键字,仍是java的内存分配,java会将new的对象放在堆中,这一部分对象是在运行时建立的对象。因此咱们每一次new的时候,都会建立不一样的对象,即使是堆中已经有了一个如出一辙的。
下面的程序将验证上面的说法。
- String str1 = "abc";
- String str2 = new String("abc");
-
- String str3 = "abc";
- String str4 = new String("abc");
-
- System.out.println(str1==str2);
-
- System.out.println(str1 == str3);
- System.out.println(str2 == str4);
-
-
-
-
-
- str2 = str2.intern();
- System.out.println(str1==str2);
-
- //output:
- //false
- //true
- //false
- //true
以上程序中用两种方式建立的4个对象,”==”比较的是地址,从结果能够看到str1和str3相同,指向同一个对象。而str2和str4比较返回结果是false,说明str2和str4指向的不是同一个对象。
(上面用到了一个比较少见的方法:intern。在str2调用了intern方法后对str1和str2进行比较返回true,能够从代码注释中看明白,intern方法返回常量池中内容和该对象相同的对象,若是常量池中不存在,则将该对象加入到常量池中。)
String对象是不变的,那为何能够进行str+=”abc”这样的操做?其实相似这样的操做是新生成了一个String对象,包含str和abc链接后的字符串。
- package test;
- public class StringTest {
- public static void main(String[] args) {
- String str1 = "abc";
- str1 += "123";
- }
- }
从编译以后的class能够看出编译器自动引入了StringBuilder类,经过它的初始化方法建立了StringBuilder对象,经过append方法添加了内容,调用toString返回链接后的对象。以上内容证实了String对象是不可变的,链接操做实际是返回了新的对象。若是是循环屡次进行链接,将不断的建立StringBuilder对象,append新内容,toString成String对象。这就带来了String类处理字符串更改操做的效率问题。
- public class StringTest {
- public static void main(String[] args) {
- long start, end;
-
- StringBuilder strBuilder = new StringBuilder(" ");
- start = System.currentTimeMillis();
- for (int i = 0; i < 100000; i++) {
- strBuilder.append(" ");
- }
- end = System.currentTimeMillis();
- System.out.println("StringBuilder append: " + (end - start) + "ms");
-
- String str = " ";
- start = System.currentTimeMillis();
- for (int i = 0; i < 100000; i++) {
- str += " ";
- }
- end = System.currentTimeMillis();
- System.out.println("String +: " + (end - start) + "ms");
- }
- }
能够看到String和StringBuilder在效率方便的差距。
- StringBuffer:A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified.
- StringBuilder:A mutable sequence of characters. This class provides an API compatible with StringBuffer, but with no guarantee of synchronization.
StringBuffer是可变的、线程安全的字符串。StringBuilder就是StringBuffer的非线程同步的版本,两者的方法差很少,只是一个线程安全(适用于多线程)一个没有线程安全(适用于单线程)。