【JAVA】String类学习笔记

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;
}




    

     

猜你喜欢

转载自blog.csdn.net/AntioniaMao/article/details/80343565