在做實驗的時候,中間有一個任務為一個圖的toString.,用來打印每條邊每個點的信息。
其中用到了字符串的鏈接 我當時用的是String 的 “+”操作,
但是圖怎么也無法輸出,因為有三十多萬條邊,在大量的字符串的拼接的時候,“+”特別耗時間和內存。
然后我通過網上查找,選擇用StringBuilder的方法解決了這個問題。
StringBuilder str = new StringBuilder(); str.append("lalalallal"); for(int i=0;i<5;i++) str.append("lalalallal"); System.out.println(str);
但是當時也沒有仔細想原理是什么,而后來復習到mutable(可變數據類型)和immutable(不可變數據類型)的時候才仔細思考了這個問題,String和StringBuilder正好是它們的典型代表。
String是immutable的變量,一旦被創建,它的值就不能被改變。注意:改變一個變量是將該變量指向另一個值的存儲空間,二改變一個變量的值是將該變量當前指向的值的存儲空間寫入一個新的值。
通過分析snapshot diagram我們發現,當string "+"的時候,是新建了一個String空間然后將原來變量的指向這個空間。原來的String被廢棄只能等待着被垃圾回收。又通過后來學習的垃圾回收的機制我們知道這是非常浪費資源的,當然也有其安全性。
而StringBuilder則是直接修改,所以執行起來很快。
其實這只是區別的一部分,因為這種機制的不同還帶來了很多很多潛在的bug
比如:
List<String> list =new LinkedList<>(); String s1 = new String("aaa"); list.add(s1); System.out.println(list.contains(s1));//true s1=s1.concat("q"); System.out.println(list.contains(s1));//false
奇怪的是,把s1加入到list之后,修改了s1,此時s1就不包含在list里面了
通過snapshot diagram可以看見這種現象的原因。List是直接指向元素所在的空間,當修s1之后,s1的引用改變,此時s1指向的空間也已經改變,不再是從前的s1了。
比如:
String s="ab"; String t=s; s=s+"c"; System.out.println(t);//ab
因為雖然t指向了s,但是s改變之后,t指向的值並沒有改變,因為此時s是重新指向了新的區域。
因此,我們在選擇合適的類型的時候,要仔細考慮的有安全、效率、還要多個引用帶來的潛在的bug