正如我們?cè)谏厦嫖恼绿岬降膬?nèi)容妹沙,在英文語境中上面 2 個(gè)方法還是有區(qū)別的儿倒,在中文環(huán)境下主要表達(dá)就是字符串壓縮错蝴。
JDK 6 使用的壓縮字符串方法,主要原因是我們修改了 String 的存儲(chǔ)結(jié)構(gòu)摇幻,char[]在 Java 的很多地方都會(huì)用到横侦,并且 String 因?yàn)檫@個(gè)修改就只能接受使用char[]為參數(shù)的構(gòu)造方法了。
在很多算法中绰姻,String 的操作又嚴(yán)重依賴char[]數(shù)組枉侧,如果我們進(jìn)行這樣修改的話,很多程序的代碼都會(huì)需要跟著修改狂芋,這個(gè)顯然是不劃算的榨馁。
在后面我們使用的縮小字符串的處理方案來說也會(huì)有問題的,同樣也會(huì)增加一些不少的問題银酗,例如會(huì)導(dǎo)致一些方法修改為內(nèi)部方法intrinsified同時(shí)一些 JIT compiler 編譯的代碼也需要進(jìn)行改進(jìn)。
因?yàn)榇鎯?chǔ)方式的改變徒像,也會(huì)有一些反人類的情況會(huì)出現(xiàn):
LATIN-1 的indexOf(String)方法調(diào)用的是內(nèi)部方法黍特,但是indexOf(char)不是小的。
在 UTF-16 環(huán)境下锯蛀,這 2 個(gè)方法都可以使用相同的內(nèi)部方法灭衷,這個(gè)問題只會(huì)對(duì) LATIN-1 字符集的 String 字符串有影響,并且也會(huì)在后續(xù)的版本中修正旁涤。
整體來說使用縮小字符串( Compact String)的效率更高一些翔曲。
你可以將 Java 應(yīng)用程序的 Heap 內(nèi)存空間 dump 出來后進(jìn)行分析,針對(duì) String 的改進(jìn)不會(huì)對(duì)你應(yīng)用程序的提高產(chǎn)生非常顯著的影響劈愚,如果你的程序有很多邏輯上面的問題瞳遍,修改程序上面的邏輯問題比考慮如何使用 String 要實(shí)際得多。
但是對(duì) JVM 來說這種提高還是有必要的菌羽。
讓我們通過下面的一個(gè)簡單的測(cè)試來看看啟用縮小字符串( Compact String)配置和不啟用這個(gè)配置對(duì)性能產(chǎn)生的異同掠械。
long startTime = System.currentTimeMillis(); List strings = IntStream.rangeClosed(1,10_000_000)? .mapToObj(Integer::toString)? .collect(toList()); long totalTime = System.currentTimeMillis() - startTime;System.out.println("Generated "+ strings.size() +" strings in "+ totalTime +" ms.");startTime = System.currentTimeMillis();Stringappended = (String) strings.stream()? .limit(100_000)? .reduce("",(l, r)->l.toString() + r.toString()); totalTime = System.currentTimeMillis() - startTime;System.out.println("Created string of length "+ appended.length()? +" in "+ totalTime +" ms.");
在這里,我們首先使用一個(gè)基本的方法來創(chuàng)建 1千萬個(gè) String 字符串注祖,然后使用默認(rèn)開啟的配置來看看上面的代碼的輸出:
Generated10000000strings in854ms.Createdstring of length488895in5130ms.
同樣的猾蒂,我們禁用 JVM 的這個(gè)參數(shù)-XX:-CompactStrings參數(shù)選項(xiàng)再來看看輸出:
Generated10000000strings in936ms.Createdstring of length488895in9727ms.
通過上面的代碼,我們可以看到上面 2 個(gè)參數(shù)修改后對(duì)比的輸出并不是非常的明顯是晨,但是也可以看到有明確的性能提升肚菠。