1. 程式人生 > >Java中的字串操作(比較String,StringBuiler和StringBuffer)

Java中的字串操作(比較String,StringBuiler和StringBuffer)

## 一、前言 剛開始學習Java時,作為只會C語言的小白,就為其中的字串操作而感到震撼。相比之下,C語言在位元組陣列中儲存一個結尾的\0去表示字串,想實現字串拼接,還需要呼叫strcpy庫函式或者自己手動去複製陣列,非常麻煩,更別提其他複雜操作,而Java通過String類讓字串操作變得十分簡單和方便。除此之外,還有stringbuilder等這些類的輔助,那麼本文就**從String,StringBuiler和StringBuffer的區別開始,去探討Java中的字串操作。** ## 二、String,StringBuiler和StringBuffer ### 2.1 String類 Java 提供了 String 類來建立和操作字串。在原始碼中可以看到**,String類內部的實現也是一個位元組陣列**,這個陣列是final型別的,因此**String是不可變的物件,每次在對String類進行改變的時候都會生成一個新的string物件,**然後將指標指向新的string物件。 ### 2.2 StringBuiler 類 和 String 類不同的是,StringBuilder 類的物件**能夠被多次的修改,並且不產生新的物件**。這個特性的意義在於,如果我們進行大量的字串操作,使用String類就會產生很大的效能消耗,而StringBuilder就可以避免這個問題。 ### 2.3 StringBuffer 類 StringBuffer 和StringBuiler之間的最大不同在於 **StringBuilder 的方法不是執行緒安全的**。 由於 StringBuilder 相較於 StringBuffer 有速度優勢,所以多數情況下建議使用 StringBuilder 類。然而在應用程式要求執行緒安全的情況下,則必須使用 StringBuffer 類。 ### 2.4 String,StringBuiler和StringBuffer的比較(對比C/C++) | 操作型別 | 說明 | **是否可變** | **執行緒安全性** | **效能** | | :-------------------: | -------------------------------------------------------- | ------------ | :------------------------: | :------- | | Java中的String | String 類中使用 final
關鍵字修飾字符陣列來儲存字串 | 不可變 | 執行緒安全 | 低 | | Java中的StringBuffer | 字串變數 | 可變 | 執行緒安全 | 一般 | | Java中的StringBuilder | 字串變數 | 可變 | 執行緒不安全 | 一般 | | C/C++ 中的char* 操作 | char *是一個指標,可以
指向一個字串陣列 | 可變 | 不可知 | 高 | | C/C++中的char陣列 | 用一個字元陣列來儲存字串 | 不可變 | 不可知 | 高 | | C/C++中的String封裝類 | string可以被看成是以字元
為元素的一種容器。 | 可變 | 併發讀操作
是執行緒安全的 | 較高 | ## 三、各種字串操作的效率測試 ### 3.1 測試程式碼 ```java @Test public void test() { int count = 100000; long startTime = System.currentTimeMillis(); String str = ""; for(int i = 0; i< count; i++){ str += i; } System.out.println("執行"+count+"次 String 耗時:"+ getRunTime(startTime)); startTime = System.currentTimeMillis(); StringBuilder stringBuilder = new StringBuilder(""); for (int i = 0; i < count; i++) { stringBuilder.append(i); } System.out.println("執行"+count+"次 StringBuilder 耗時:"+ getRunTime(startTime)); startTime = System.currentTimeMillis(); StringBuffer stringBuffer = new StringBuffer(""); for (int i = 0; i < count; i++) { stringBuffer.append(i); } System.out.println("執行"+count+"次 StringBuffer 耗時:"+ getRunTime(startTime)); } ``` ### 3.2 測試結果 ``` 執行100000次 String 耗時:32s 執行100000次 StringBuilder 耗時:2ms 執行100000次 StringBuffer 耗時:4ms ``` ### 3.3 小結 可以看到String類的效能遠低於StringBuiler和StringBuffer,而StringBuiler在本次測試中比Stringbuffer提高了50%的效能 ## 四、Java字串和正則表示式 ### 4.1 測試程式碼 ```java @Test public void test0(){ //郵政編碼 String postCode = "[1-9]\\d{5}"; //區號-座機號碼 String areaCode = "\\d{3}-\\d{8}|\\d{4}-\\d{7}"; //手機號碼 String phone = "(?:13\\d|15\\d|18\\d)\\d{5}(\\d{3}|\\*{3})"; String text = "郵政編碼:440834"+ "區號-座機號碼: 020-12345678"+ "手機號:13536373839"+ "郵政編碼:440833"+ "區號-座機號碼: 010-12345678"+ "手機號:13536373739"; Pattern p = Pattern.compile(postCode); Matcher m = p.matcher(text); System.out.println("文字中包含郵政編碼:"); while (m.find()){ System.out.println(m.group()); } p = Pattern.compile(areaCode); m= p.matcher(text); System.out.println("文字中包含區號-座機號碼:"); while (m.find()){ System.out.println(m.group()); } p = Pattern.compile(phone); m= p.matcher(text); System.out.println("文字中包含手機號:"); while (m.find()){ System.out.println(m.group()); } } ``` ### 4.2 測試結果 ``` 文字中包含郵政編碼: 440834 123456 135363 440833 123456 135363 文字中包含區號-座機號碼: 020-12345678 010-12345678 文字中包含手機號: 13536373839 13536373739 ``` ## 五、總結 經過測試和比較,可以看到Java中同為字串操作,但由於背後實現的原理不同,形成的效能差異也是十分巨大,相比之下,C/C++中的字串操作效能更高。String類的效能遠低於StringBuiler和StringBuffer,而StringBuiler比Stringbuffer的效能稍微高一點。對效能的探究,最終還是要回到使用場景,**可以總結得出,如果不涉及字串操作,那麼String類是首選,如果涉及的字串操作沒有執行緒安全問題,那麼使用StringBuilder,如果涉及的字串操作存線上程安全問題,那麼使用StringBuffer** ## 六、參考資料 - [探祕Java中的String、StringBuilder以及StringBuffer](https://www.cnblogs.com/dolphin0520/p/3778589探祕Java中的String、StringBuilder以及StringBuffer.html) - [java中String StringBuilder StringBuffer比較和效率(效能)測試 - 行者老夫 - 部落格園](https://www.cnblogs.com/xzlf/p/12681547.html) - [Java 正則表示式](https://www.runoob.com/java/java-regular-expression