为什么80%的码农都做不了架构师?>>>
substring(int beginIndex, int endIndex) 方法在 JDK 6 和 JDK 7 中是不一样的. 了解他们之间的异同可以让你更好地使用这个方法. 为了方便表达,下文中使用 followingsubstring() 代替 substring(int beginIndex, int endIndex) 。
1. substring() 都做了什么操作?
substring(int beginIndex, int endIndex) 返回一个从 beginIndex 开始到endIndex-1结束字符串 。
String x = "abcdef"; x = x.substring(1,3); System.out.println(x);
Output:
bc
2. 当 substring() 被调用的时候会发生什么?
因为字符串x是不可变的, 当x.substring(1,3)方法返回的字符串赋值给x, 它会像下图那样指向一个全新的字符串:
但是上面的图并不是完全的正确描述了substring()方法被调用的时候内存发生了什么变化,它仅仅描述了 堆内存中发生了什么.
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:
|
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));