String與StringBuffer效率對比


昨天申請了一個LeetCode的賬號,先刷了一題最基礎的,字符串逆序輸出。

我先寫出了如下代碼:

public class Solution {
    public String reverseString(String s) {
        String rev = "";
        for(int i = s.length()-1; i >= 0; i--){
            rev += s.charAt(i);
        }
        return rev;
    }
}

這份代碼在OJ上運行的結果是Time Limit Exceeded,也就是超時了,顯然效率太低。

我又改成如下代碼,把String類換成StringBuffer類:

public class Solution {
    public String reverseString(String s) {
        StringBuffer rev = new StringBuffer();
        for(int i = s.length()-1; i >= 0; i--){
            rev.append(s.charAt(i));
        }
        return rev.toString();
    }
}

這份代碼可以通過,並且用時只有6ms。

為什么String類和StringBuffer類的效率會相差這么多呢?我上網查了資料,主要是以下原因。

 

String類的對象其實是一個常量,例如String s = "abc"; 那么s其實是一個常量,它的值就是"abc",不能改變。

Java所提供的String操作方法,比如直接進行 '+' 運算,其實是作了封裝,給了使用者能對String對象進行增加或刪除的錯覺,本質上並不是如此。

當我們執行 s += "def"; 時,並不是說 s 的內容直接由"abc"變為了"abcdef","abc"仍是"abc","def"會被暫時存儲到一塊新的內存里,然后再開辟一個新的內存空間,把"abc"和"def"拷貝到這個內存空間,然后 s 指向這個新的內存空間。

這個過程其實就是new了一個新的String對象,新對象是"abcdef",s 拋棄了原來的對象,指向了新對象。

由於每次操作都要重新new一個對象,並且占用大量內存,因此String類的效率不高。

 

那么StringBuffer呢?

 

StringBuffer對象是一個長度可變的對象,當對StringBuffer的進行增加或刪除時,不需要new一個對象,可以動態地修改堆內存。

StringBuffer提供了append方法,在字符串的末尾進行添加。實際上,String類進行 '+' 運算,就是創建了一個StringBuffer對象,然后調用append進行添加,最后調用toString把StringBuffer轉化為String。

顯然,String的效率絕對不如StringBuffer了。

 

可以再看一個直觀的測試樣例:

    public static void main(String[] args){
        String toappend = "abcdefghijklmnopqrstuvwxyz";//26個字母,用於每次添加
        int times = 20000;//添加20000次
        //使用String類,將26個字母添加20000次
        long start = System.currentTimeMillis();
        String str = "";
        for(int i = 0; i < times; i++){
            str += toappend;
        }
        long end = System.currentTimeMillis();
        System.out.println("String time = " + (end-start)+" ms");
        
     //使用StringBuffer類,將26個字母添加20000次 start
= System.currentTimeMillis(); StringBuffer strbuf = new StringBuffer(); for(int i = 0; i < times; i++){ strbuf.append(toappend); } end = System.currentTimeMillis(); System.out.println("StringBuffer time = " + (end-start)+" ms"); }

運行結果: 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM