substring(int beginIndex, int endIndex) 方法在 JDK 6 和 JDK 7 中是不同的. 瞭解他們之間的異同可讓你更好地使用這個方法. 爲了方便表達,下文中使用 followingsubstring() 代替 substring(int beginIndex, int endIndex) 。 java
1. substring() 都作了什麼操做? 數組
substring(int beginIndex, int endIndex) 返回一個從 beginIndex 開始到endIndex-1結束字符串 。 app
String x = "abcdef"; x = x.substring(1,3); System.out.println(x);
Output: 性能
bc ui
2. 當 substring() 被調用的時候會發生什麼? this
由於字符串x是不可變的, 當x.substring(1,3)方法返回的字符串賦值給x, 它會像下圖那樣指向一個全新的字符串: spa
可是上面的圖並非徹底的正確描述了substring()方法被調用的時候內存發生了什麼變化,它僅僅描述了 堆內存中發生了什麼. code
3. substring() in JDK 6 索引
字符串內部是用字符數組來實現的. 在 JDK 6 中, String 包含了3個字段: char value[], int offset, int count. 用它們來存儲一個字符數組, 數組在內存中的第一個索引, 字符串包含字符的數量. 內存
當 substring() 方法被調用的時候, 它會建立一個新的字符串, 但字符串的值仍然指向堆內存中原來的字符串值. 這兩個字符串的不一樣在於它們的offset和 count.
下面的代碼簡單的演示了發生了什麼操做
//JDK 6 String(int offset, int count, char value[]) { this.value = value; this.offset = offset; this.count = count; } public String substring(int beginIndex, int endIndex) { //check boundary return new String(offset + beginIndex, endIndex - beginIndex, value); }
4. 在 JDK 6中調用substring()可能會致使一個性能問題
若是你有一個很是長的字符串, 但你每次調用 substring()的時候只截取其中很小的一部分. 由於你只須要很小的一部分,可是在內存中存儲了一個很長的數組,這樣會致使程序性能很差. 在 JDK 6 中, 咱們將會使用下面的方法來解決這個問題, 它會指向一個新的sub string:
x = x.substring(x, y) + "" |
5. substring() in JDK 7
這個方法在JDK 7中有了提高,每一次調用substring()都會在堆內存中建立一個新的字符串數組
//JDK 7 public String(char value[], int offset, int count) { //check boundary this.value = Arrays.copyOfRange(value, offset, offset + count); } public String substring(int beginIndex, int endIndex) { //check boundary int subLen = endIndex - beginIndex; return new String(value, beginIndex, subLen); }
/**************************我是分隔線******************************/
下面的網友評論中有人提出x = x.substring(x, y) + ""這個方法很差,由於它等同於
StringBuilder sb = new StringBuilder(); sb.append(x.substring(x, y)); sb.append(""); x = sb.toString();
能夠用下面的方法來代替x = x.substring(x, y) + ""
x = new String(x.substring(x, y));