今天在敲程式碼的時候,無意間看到這樣一個提示:
英文不太好,先問問ChatGPT,這個啥意思?
IDEA 提示你,可以將程式碼中的 StringBuilder 替換為簡單的字串連線方式。
提示資訊中說明了使用 StringBuilder 進行字串拼接在現代 JVM 中並不一定比使用 String 連線有顯著的效能優勢,尤其是對於簡單的字串拼接操作,直接使用 String 連線可能更加簡潔明瞭。
可以被替換為:
String str = "哪吒程式設計" + "study" + "ChatGPT4o";
這樣可以使程式碼更簡潔,同時在大多數情況下不會對效能產生明顯的負面影響。
IDEA 提供了自動替換的選項,點選提示框中的 “Replace 'StringBuilder' with 'String'” 即可自動進行替換。
實際上,從JDK1.5開始,Java編譯器就做了自動最佳化,使用“+”拼接字串,編譯器編譯後自動最佳化為使用StringBuilder。
做一個小測試,拼接10000個"哪吒程式設計" + "study" + "ChatGPT4o"
,看下使用“+”拼接字串和使用StringBuilder,哪個速度快。
public class StringTest { public static void main(String[] args) throws IOException { // long timeSum = 0; // for (int i = 0; i < 3; i++) { // timeSum += spliceStrByAdd(); // } // System.out.println("使用+拼接字串平均耗時: " + timeSum/3 +"毫秒"); long timeSum = 0; for (int i = 0; i < 3; i++) { timeSum += spliceStrByBuilder(); } System.out.println("使用StringBuilder拼接字串平均耗時: " + timeSum / 3 + "毫秒"); } private static final int n = 10000; /** * 使用+拼接字串 * * @return */ private static long spliceStrByAdd() { Instant start = Instant.now(); String ret = ""; for (int i = 0; i < n; i++) { ret += "哪吒程式設計" + i; ret += " study" + i; ret += " ChatGPT4o" + i; } Instant end = Instant.now(); Duration elapsed = Duration.between(start, end); long time = elapsed.toMillis(); System.out.println("使用+拼接字串耗時: " + time + "毫秒"); return time; } /** * 使用StringBuilder拼接字串 */ private static long spliceStrByBuilder() { Instant start = Instant.now(); StringBuilder builder = new StringBuilder(); for (int i = 0; i < n; i++) { builder.append("哪吒程式設計").append(i); builder.append(" study").append(i); builder.append(" ChatGPT4o").append(i); } Instant end = Instant.now(); Duration elapsed = Duration.between(start, end); long time = elapsed.toMillis(); System.out.println("使用StringBuilder拼接字串耗時: " + time + "毫秒"); return time; } }
這差距還真是巨大,相差1000倍,Idea給的提示這不是胡扯嘛?
上面還說,jdk1.5開始,+在編譯時自動最佳化為StringBuilder,現在我用jd-gui對class檔案進行反編譯,檢視編譯後的程式碼差異。
這個時候,很多槓精就該站出來了,你這測試有問題,不能這麼幹
你這迴圈拼接10000次,透過+拼接時,你就建立了10000個字串,你這測試的並不是純+拼接耗時!!!
好像說的有點道理~
public class StringTest2 { public static void main(String[] args) throws IOException { long timeSum = 0; for (int i = 0; i < 3; i++) { timeSum += spliceStrByAdd(); } System.out.println("使用+拼接字串平均耗時: " + timeSum/3 +"毫秒"); timeSum = 0; for (int i = 0; i < 3; i++) { timeSum += spliceStrByBuilder(); } System.out.println("使用StringBuilder拼接字串平均耗時: " + timeSum / 3 + "毫秒"); } private static final int n = 10000; /** * 使用+拼接字串 * * @return */ private static long spliceStrByAdd() { Instant start = Instant.now(); for (int i = 0; i < n; i++) { String ret = "哪吒程式設計" + i + " study" + i+" ChatGPT4o" + i; } Instant end = Instant.now(); Duration elapsed = Duration.between(start, end); long time = elapsed.toMillis(); System.out.println("使用+拼接字串耗時: " + time + "毫秒"); return time; } /** * 使用StringBuilder拼接字串 */ private static long spliceStrByBuilder() { Instant start = Instant.now(); for (int i = 0; i < n; i++) { StringBuilder builder = new StringBuilder(); builder.append("哪吒程式設計").append(i); builder.append(" study").append(i); builder.append(" ChatGPT4o").append(i); } Instant end = Instant.now(); Duration elapsed = Duration.between(start, end); long time = elapsed.toMillis(); System.out.println("使用StringBuilder拼接字串耗時: " + time + "毫秒"); return time; } }
使用+和StringBuilder單獨拼接字串時,效率上確實差不多少!
也就是說,在拼接少量字串的時候,使用+也是可以的,Idea的提示還是有點道理的!