1.public boolean equals(Object anObject)
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
判断流程:
引用是否相同,相同则返回true->anObject是否是String类->判断this和anObject的长度是否相同->比较每个字符是否相同
疑问:
1.第二个if语句块中,如果已经判断anObject是String类了(且由于String类为final不可继承,所以anObject也不可能是其子类的实例),为什么还要声明一个anotherString呢?不直接使用anObject呢?
引用百度百科:【java中的instanceof运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。】
2.public boolean equalsIgnoreCase(String anotherString)
public boolean equalsIgnoreCase(String anotherString) {
return (this == anotherString) ? true
: (anotherString != null)
&& (anotherString.value.length == value.length)
&& regionMatches(true, 0, anotherString, 0, value.length);
}
执行流程:判断是否为相同引用->判断anotherString是否为空、长度是否相等、调用regionMatches方法
2.1 public boolean regionMatches(boolean ignoreCase,int toffset,String other,int ooffset,int len)
public boolean regionMatches(boolean ignoreCase, int toffset,
String other, int ooffset, int len) {
char ta[] = value;
int to = toffset;
char pa[] = other.value;
int po = ooffset;
// Note: toffset, ooffset, or len might be near -1>>>1.
if ((ooffset < 0) || (toffset < 0)
|| (toffset > (long)value.length - len)
|| (ooffset > (long)other.value.length - len)) {
return false;
}
while (len-- > 0) {
char c1 = ta[to++];
char c2 = pa[po++];
if (c1 == c2) {
continue;
}
if (ignoreCase) {
// If characters don't match but case may be ignored,
// try converting both characters to uppercase.
// If the results match, then the comparison scan should
// continue.
char u1 = Character.toUpperCase(c1);
char u2 = Character.toUpperCase(c2);
if (u1 == u2) {
continue;
}
// Unfortunately, conversion to uppercase does not work properly
// for the Georgian alphabet, which has strange rules about case
// conversion. So we need to make one last check before
// exiting.
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
continue;
}
}
return false;
}
return true;
}
Coding技巧:【14 15行,把当前需要进行比较的字符单独提取出来,可以避免每一种情况判断后都需要执行to++和po++】
这个方法是用于判断两个字符串在指定范围内是否匹配的。
boolean:ignoreCase:用于指示是否要忽略大小写
toffset:本字符串用于匹配的子区域的起始偏移量
other:另一个用于匹配的字符串
ooffset:other字符串用于匹配的子区域的起始偏移量
len:需要比较的字符数量
regionMatches(true, 0, anotherString, 0, value.length);
这个方法代表忽略大小写,原字符串和other字符串均从第一个字符开始比较,比较的长度为原字符串的总长度
3.public int lastIndexOf(String str)方法调用链
->public int lastIndexOf(String str,int fromIndex)
->static int lastIndexOf(char[] source,int sourceOffset,int sourceCount,char[] target,int targetOffset,int targetCount,int fromIndex)
char[] source:源字符数组
int sourceOffset:源字符数组偏移量
char[] target:用于匹配的字符数组
int targetOffset:匹配的字符数组偏移量
int fromIndex:匹配偏移量
static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
/*
* Check arguments; return immediately where possible. For
* consistency, don't check for null str.
*/
int rightIndex = sourceCount - targetCount;
if (fromIndex < 0) {
return -1;
}
if (fromIndex > rightIndex) {
fromIndex = rightIndex;
}
/* Empty string always matches. */
if (targetCount == 0) {
return fromIndex;
}
int strLastIndex = targetOffset + targetCount - 1;
char strLastChar = target[strLastIndex];
int min = sourceOffset + targetCount - 1;
int i = min + fromIndex;
startSearchForLastChar:
while (true) {
while (i >= min && source[i] != strLastChar) {
i--;
}
if (i < min) {
return -1;
}
int j = i - 1;
int start = j - (targetCount - 1);
int k = strLastIndex - 1;
while (j > start) {
if (source[j--] != target[k--]) {
i--;
continue startSearchForLastChar;
}
}
return start - sourceOffset + 1;
}
}
1.先对无效情况做一个判断
rightIndex为合法的最右边界序号(用于匹配的索引最大值,超过这个值源字符数组的数量小于待匹配的字符数组)
合法性校验->修正fromIndex到合法的最大索引值rightIndex
int rightIndex = sourceCount - targetCount;
if (fromIndex < 0) {
return -1;
}
if (fromIndex > rightIndex) {
fromIndex = rightIndex;
}
/* Empty string always matches. */
if (targetCount == 0) {
return fromIndex;
}
2.声明一些变量,具体等会儿再来补充,先洗脑壳去了
int strLastIndex = targetOffset + targetCount - 1;
char strLastChar = target[strLastIndex];
int min = sourceOffset + targetCount - 1;
int i = min + fromIndex;
startSearchForLastChar:
while (true) {
while (i >= min && source[i] != strLastChar) {
i--;
}
if (i < min) {
return -1;
}
int j = i - 1;
int start = j - (targetCount - 1);
int k = strLastIndex - 1;
while (j > start) {
if (source[j--] != target[k--]) {
i--;
continue startSearchForLastChar;
}
}
return start - sourceOffset + 1;
}
}
while (i >= min && source[i] != strLastChar) { i--; }这段代码是为了让i定位到源字符串中从尾巴开始,找到的第一个和目的字符串最后一个字符相匹配的索引序号
如果说i<min,那么剩下的字符长度已经小于了目的字符串长度了,匹配失败,返回-1
如果i>=min,那么我们就开始从倒数第二个字符开始进行对比,查看是否匹配
start=j-(targetCount-1) 这个start是用标识匹配终点(因为是逆向匹配,所以其实这个终点,应该是正向来看的起点)
4.public String replace(char oldChar, char newChar)
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;
int i = -1;
char[] val = value; /* avoid getfield opcode */
while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
if (i < len) {
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;
}
(1)为什么i初值为-1 且while中是++i而不是i++呢?
我的理解是:如果考虑两种情况:
1.遍历完整个字符数组后都都未发现和oldChar相等的字符,那么i++和++i都一样没有什么区别;
2.但如果发现了与oldChar匹配的字符,则break出while循环,使用++i的话,那么接下来的代码中i就等于匹配的这个字符的位置,而i++就会使下一次使用i的时候,使i的值+1
(2)为什么要先有一个循环来找到第一个和oldChar匹配的字符的位置呢?为什么不在一个while循环里直接进行判断和替换呢?
为了在没有与oldChar匹配的字符的情况下,直接return this;来减少系统开销???
但是如果为了减少开销,也可以直接在一个while循环里判断并替换,申请一个int count来记录替换的个数,如果count==0,那么直接返回this也可以减少系统开销啊???
我这样写有弊端??待查证,令人窒息
public String replace(char oldChar,char newChar){
if(oldChar!=newChar){
int len=value.length;
int i=0;
int count=0;
char[] val=value;
while(i<len){
if(val[i]==oldChar){
val[i]=newChar;
count++;
}
++i;
}
if(count!=0){
return new String(val,true);
}
}
return this;
}