java源码分析(3)-String(2)

时间:2023-02-26 08:19:19

1.substring

substring方法用于对字符串的截取,在数据的传递过程中使用的十分普遍,但消耗的性能较大,建议能不用尽量不用。
public String substring(int beginIndex) {//String截取方法,传入截取开始的下标
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);//当传入的开始下标符合且不为0时,新建一个String,注意这个String的值并没有变化,只是改变了偏移量

}
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);//与上面的方法类似,没有改变String的value属性,只是而是
改变了偏移量和count长度。
}

2.replace

public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;//替代的是整个value中的oldChar,而不是从偏移量开始替代
int i = -1;
char[] val = value;

while (++i < len) {//先遍历数组中是否有原字母,没有就无需替换,高效的设计
if (val[i] == oldChar) {
break;
}
}
if (i < len) {//获得需要替换的char的下标,此下表以前的char直接复制,
此下标以后的char才开始一个一个比较,若等于oldchar则替换,高效
char buf[] = new char[len];
for (int j = 0; j < i; j++) {
buf[j] = val[j];//
}
while (i < len) {
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new String(buf, true);
}
}
return this;
}

3.indexOf

static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);//当目标查询的字符串为空,且起始值大于源字符串的长度,返回源字符串的有效长度
}
if (fromIndex < 0) {//查询起始下标小于0时,自动改为0
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;//起始下标为0,直接返回起始下标
}
char first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);//先设置一个最大的源字符串的下标,可以节省循环次数

for (int i = sourceOffset + fromIndex; i <= max; i++) {
if (source[i] != first) {
while (++i <= max && source[i] != first);//找到源字符串中起始下标后第一个与目标字符串第一个字符相同的下标
}
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;//设置比较的字符串结束的下标的末尾
for (int k = targetOffset + 1; j < end && source[j]
== target[k]; j++, k++);
if (j == end) {
return i - sourceOffset;//比较目标字符串长度的字符,若全相等,则表示查找到了目标字符串,返回偏移量(目标字符串起始值)
}
}
}
return -1;
}

4.split

public String[] split(String regex, int limit) {

char ch = 0;
if (((regex.value.length == 1 &&
".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||//分隔符长度为1时,$|()[{^?*+\\不能当作分隔符
(regex.length() == 2 &&
regex.charAt(0) == '\\' &&
(((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&//当长度为2时且第一个字符为“\\”转义字符,第二个字符不是字符0-9 a-z A-Z 以及utf-16之间的字符
((ch-'a')|('z'-ch)) < 0 &&
((ch-'A')|('Z'-ch)) < 0)) &&
(ch < Character.MIN_HIGH_SURROGATE ||
ch > Character.MAX_LOW_SURROGATE))
{
int off = 0;
int next = 0;
boolean limited = limit > 0;
ArrayList<String> list = new ArrayList<>();
while ((next = indexOf(ch, off)) != -1) {
if (!limited || list.size() < limit - 1) {
list.add(substring(off, next));//每次将截取到的字符串添加到list中,并将off设置为next的下一个字符,作为下次截取的开始值
off = next + 1;
} else { // last one
//assert (list.size() == limit - 1);
list.add(substring(off, value.length));//最后一次截取时off默认为最长
off = value.length;
break;
}
}
if (off == 0)
return new String[]{this};//若字符串中不存在截取符,则直接返回原字符串

// Add remaining segment
if (!limited || list.size() < limit)
list.add(substring(off, value.length));

// Construct result
int resultSize = list.size();
if (limit == 0)
while (resultSize > 0 && list.get(resultSize - 1).length() == 0)//将list中的空位去除,并返回最后一个值的下标
resultSize--;
String[] result = new String[resultSize];
return list.subList(0, resultSize).toArray(result);//截取list的中所有有效地值,将之放入string数组后返回中
}
return Pattern.compile(regex).split(this, limit);
}