字符串是軟件開發中最重要的對象之一。一般,字符串對象在內存中是佔據了最大的空間塊,所以如何高效地處理字符串,必將是提升總體性能的關鍵所在。正則表達式
Java中八大基本數據類型沒有String類型,由於String類型是Java對char數組的進一步封裝。算法
String類的實現主要由三部分組成:char數組,offset偏移量,String的長度。數組
String類型有三個基本特色:安全
不變性性能優化
不變性是指String對象一旦生成,則不能再對它進行改變。多線程
不變性的做用在於當一個對象須要被多線程共享,而且頻繁訪問時,能夠省略同步和鎖等待的時間,從而大幅提升系統性能。函數
針對常量池的優化工具
當兩個String對象擁有相同的值時,它們只引用常量池中的同一個拷貝。性能
類的final定義單元測試
做爲final類的String對象在系統中不能有任何子類,這是對系統安全性的保護!
關於這一點,在JDK的1.7及之後就已經解決了!
在1.7以前,subString()方法截取字符串只是移動了偏移量,截取以後的字符串實際上仍是原來的大小。
如今,當使用subString()方法截取字符串時會把截取後的字符串拷貝到新對象。
String.split()方法使用簡單,功能強大,支持正則表達式,可是,在性能敏感的系統中頻繁的使用這個方法是不可取的。
注意 * ^ : | . 這些符號記得\\轉義
StringTokenizer類是JDK中提供的專門用來處理字符串分割的工具類。構造方法:
public StringTokenizer(String str, String delim, boolean returnDelims)
其中str是要分割的字符串,delim是分割符,returnDelims是否返回分隔符,默認false。
String s = "a;b;c"; StringTokenizer stringTokenizer = new StringTokenizer(s, ";", false); System.out.println(stringTokenizer.countTokens()); while (stringTokenizer.hasMoreTokens()) { System.out.println(stringTokenizer.nextToken()); }
indexOf()方法是一個執行速度很是快的方法,subString()是採用了時間換空間技術,所以速度相對快。
public static List<String> mySplit(String str, String delim){ List<String> stringList = new ArrayList<>(); while(true) { int k = str.indexOf(delim); if (k < 0){ stringList.add(str); break; } String s = str.substring(0, k); stringList.add(s); str = str.substring(k+1); } return stringList; }
split()方法功能強大,可是效率最差;
StringTokenizer性能優於split方法,能用StringTokenizer就不必用split();
本身實現的分割算法性能最好,但代碼的可讀性和系統的可維護性最差,只有當系統性能成爲主要矛盾時,才推薦使用該方法。
charAt(int index) 返回指定索引處的 char 值。功能和indexOf()相反,效率卻同樣高。
public boolean startsWith(String prefix)
測試此字符串是否以指定的前綴開始
public boolean endsWith(String suffix)
測試此字符串是否以指定的後綴結束
這兩個Java內置函數效率遠遠低於charAt()方法。單元測試:
@Test public void test(){ String str = "hello"; if (str.charAt(0)=='h'&&str.charAt(1)=='e'){ System.out.println(true); } if (str.startsWith("he")){ System.out.println(true); } }
String s = "123"+"456"+"789";
雖然從理論上說字符串的累加的效率並不高,但該語句執行耗時爲0;反編譯代碼後,咱們發現代碼是
String s = "123456789";
顯然,是Java在編譯時作了充分的優化。所以,並無想象中那樣生成大量的String實例。
對於靜態字符串的鏈接操做,Java在編譯時會進行完全的優化,將多個鏈接操做的字符串在編譯時合成一個單獨的長字符串。
String str = "hello"; str+="word"; str+="!!!";
咱們利用「+=」改變字符串內容的值,實際上字符串根本沒有改變。
當 str+="word"
時,堆內存開闢了word
的內存空間和helloword
的兩個內存空間(至關於實例化了兩個String對象),並把str的引用指向了helloword
,原來的hello
和word
成爲了垃圾被JVM回收。
String的concat()是專門用於字符串鏈接操做的方法,效率遠遠高於「+」或者「+=」。
不用多說了,就是爲字符串鏈接而生的,效率最高。不一樣的是,StringBuffer幾乎對全部的方法都作了同步,StringBuilder並無作任何同步,效率更高一些。只不過在多線程系統中,StringBuilder沒法保證線程安全,不能使用。
StringBuffer和StringBuilder的是對String的封裝,String是對char數組的封裝。是數組就有大小,就有不夠用的時候,不夠用只能擴容,也就是把原來的再複製到新的數組中。合適的容量參數天然可以減小擴容的次數,達到提升效率的目的。
在初始化時,容量參數默認是16個字節。在構造方法中指定容量參數:
public StringBuilder(int capacity)
判斷字符串相等(忽略大小寫)
equalsIgnoreCase(String anotherString)
判斷是否存在子字符串(返回布爾類型)
contains(CharSequence s)
將指定字符串鏈接到此字符串的結尾
concat(String str)
使用指定的格式字符串和參數返回一個格式化字符串
format(String format, Object... args)
使用默認語言環境的規則將此 String 中的全部字符都轉換爲小寫。
toLowerCase()
使用默認語言環境的規則將此 String 中的全部字符都轉換爲大寫。
toUpperCase()
返回字符串的副本,忽略前導空白和尾部空白。
trim()
使用給定的 replacement 替換此字符串全部匹配給定的正則表達式的子字符串。
String replaceAll(String regex, String replacement)
按字典順序比較兩個字符串,不考慮大小寫。
int compareToIgnoreCase(String str)
本文參考《Java程序性能優化》葛一鳴著