1 前言
String類是Java編程語言中最為重要的對象之一。通常,字符串對象在內存中總是佔據了很大的空間,因此,如何高效的處理字符串是提升系統性能的關鍵。這也是String操作總是出現先面試題中的原因所在。
2 String類的特點
String類是Java語言中重要的數據類型,但它並不是Java的基本數據類型。在C語言中,對字符串的處理通常的做法是使用char數組,但這種方式的弊端是顯而易見的,即數組本身無法封裝字符串操作所需要的基本方法。在Java語言中,Java的設計者對String對象進行了大量的優化,主要表現在以下3個方面:
- 不變性;
在Java語言中String字符串一旦創建,則不能再對它進行修改。這一特性主要作用於當一個對象需要被多線程共享,並且訪問頻繁時,可以省略同步和鎖等待的時間,從而大幅提高系統性能。
- 常量池;
當兩個String對象擁有相同的值時,它們只引用常量池中的同一個拷貝。當同一個字符串反覆出現時,這個技術可以大幅度節省內存空間。
- 類的final定義
作為final類的String對象在系統中不能有任何子類,這主要是對系統安全性的保護。
下面我們通過一段代碼示例,來分析一下String內存分配機制。
String s1 = "aaa";
String s2 = "aaa";
String s3 = new String("aaa");
System.out.println(s1==s2);
System.out.println(s1==s3);
System.out.println(s1==s3.intern());輸出:
true
false
true以上代碼顯示s1和s2引用了相同的地址,但是s3卻重新開闢了一塊內存空間。我們又通過intern()方法發現s1和s3所指向的實體是一樣的。由此我們可以確定s1和s3引用了常量池中的同一個引用。如下圖所示:
String常量池內存
3 String操作
3.1 字符串查找
在軟件開發過程中經常會遇到這樣的問題:判斷一個字符串的開始和結束子串是否等於某個子串。例如,判斷字符串str是否以Java開頭,通常的做法是可以使用String類的startWith()方法。但即便是這樣的Java內置函數,其效率也遠遠低於charAt()方法。
因此,在高頻率情況下建議使用charAt()方法。
3.2 字符串分割
字符串分割是處理字符串的最常用的方法之一。字符串分割是指將一個原始字符串,根據某個分割符切割成一組小字符串。
- 方案一:String對象的split()方法便實現了這個功能。 String.split()方法使用簡單,功能強大,但是效率最差,在性能敏感的系統中頻繁使用這個方法是不可取的。
- 方案二:StringTokenizer類是JDK中提供的專門用來處理字符串分割子串的工具類。
StringTokenizer性能優於split()方法,因此在能夠使用StringTokenizer的模塊中,就沒有必要使用split();
- 方案三:使用String類的兩個方法——indexOf()和substring()手動完成字符串分割算法。
雖然性能最好,但是代碼的可讀性和系統的可維護性最差。
因此,在實際的軟件開發過程中,開發人員需要在系統的各個方面進行權衡,採用最合適的方法處理問題。
3.3 字符串拼接
很多時候,程序開發過程中並不能預知字符串的實際值,因此需要在程序運行過程中通過拼接的形式動態生成字符串。例如:
String str = "大家好,"+"我是"+"碼農洞見";然而上段代碼的效率並不高,為了更高效的生成字符串,需要使用StringBuffer和StringBuilder類。
StringBuilder str = new StringBuilder();
str.append("大家好,");
str.append("我是");
str.append("碼農洞見");3.4 StringBuilder和StringBuffer的選擇
它們都實現了AbstractStringBuilder抽象類,擁有幾乎相同的對外接口。兩者的最大不同在於,StringBuffer幾乎對所有的方法都做了同步,而String-Builder並沒有做任何同步。 由於方法同步需要消耗一定的系統資源,因此StringBuilder的效率也高於StringBuffer。但是在多線程系統中,StringBuilder無法保證線程的安全,不能使用。
無論是StringBuilder還是StringBuffer,在初始化時都可以設置一個容量參數。如果能夠預先評估StringBuilder的大小,則能夠有效地減少容量擴充的操作,從而提高系統的性能。
4 碼農來洞見
很多時候,開發人員的一些不以為然的習慣往往造成了系統性能的下降。通過上面的講解我們不難發現,其實,很多優化並沒有想象中那麼複雜和困難。我們只要稍微思考權衡一下系統可能就會因為這一轉變而產生巨大的變化。不要因為這段代碼性能不差幾毫秒,然而對於一個系統來說,代碼片段量何其龐大,少許的差別累加起來就會造成幾秒甚至更大的差距。
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/234145.html
微信掃一掃
支付寶掃一掃