-
equals(Object anObject)
:
重写的equals方法,不再比较内存地址而是比较字符串是否相同。
/**
* 比较流程:
* 1.先比较对象是否相等,相等直接返回true
* 2.比较类型
* 3.比较长度
* 4.从第一个字符比到最后一个字符
*/
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;
}
- 对于Object,调用Object的
toString()
。
- 对于char和char[],返回一个新的String。
- 对于各种数字包装类,调用包装类中带参数的的
toString(int i)
(以int举例)。
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
public static String valueOf(char data[]) {
return new String(data);
}
public static String valueOf(boolean b) {
return b ? "true" : "false";
}
public static String valueOf(char c) {
char data[] = {c};
return new String(data, true);
}
public static String valueOf(int i) {
return Integer.toString(i);
}
public static String valueOf(long l) {
return Long.toString(l);
}
public static String valueOf(float f) {
return Float.toString(f);
}
public static String valueOf(double d) {
return Double.toString(d);
}
-
indexOf()
:
各种重载indexOf()
调用的底层indexOf()
方法:
/**
* 在source字符串里面搜target字符串,判断source是否包含target字符串。
* 由于对数据结构不够熟悉,且应用时基本偏移量都时0,所以将这段源码中的偏移量offset默认为0
*
* @param source 被搜字符串的字符数组
* @param sourceOffset source偏移量(一般都是0)
* @param sourceCount source字符数组的长度
* @param target 目标字符串的字符数组
* @param targetOffset target的偏移量(一般都是0)
* @param targetCount target字符数组的长度
* @param fromIndex 从fromIndex索引开始搜索
* @return 正确时返回target字符串在source字符串中的fromIndex索引起第一次出现的下标,找不到、逻辑错误等都返回-1
*/
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
//索引超出source字符串长度时,target字符串如果不是 "" 就返回-1
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
//如果目标字符串为"",直接返回fromIndex
if (targetCount == 0) {
return fromIndex;
}
//target字符串的第一个字符
char first = target[targetOffset];
//搜索的最大长度。
//从source的fromIndex开始到max结束,先比对首字符,如果首字符相同就从第二个字符开始比对到最后一个字符。如果比对失败返回-1
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
//比对首字符,比对到当i和max相等时结束
//比对不到就一直在while循环中
if (source[i] != first) {
while (++i <= max && source[i] != first) ;
}
//比对source和target数组中第二个字符起的剩余字符
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;
}
-
lastIndexOf()
:
各种重载lastIndexOf()
调用的底层lastIndexOf()
方法:
/**
* 在源字符串中从fromIndex起从右往左搜索,返回目标字符串第一次出现的下标。
* 参数和indexOf()方法中的参数相似。
*/
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;
}
//空字符串必定匹配
if (targetCount == 0) {
return fromIndex;
}
//目标字符串末尾字符的下标
int strLastIndex = targetOffset + targetCount - 1;
//目标字符串末尾字符
char strLastChar = target[strLastIndex];
//当源字符串下标从0开始,目标字符串出现在源字符串最左边时的下标
int min = sourceOffset + targetCount - 1;
//目标字符串出现在fromIndex最右边的下标
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;
}
}
-
substring(int beginIndex, int endIndex)
:按下标截取字符串
/**
* 传入开始和结束的下标,截取这段字符串并作为新的String返回
*
* @param beginIndex 开始的下标,闭区间(包含)
* @param endIndex 结束的下标,开区间(不包含)
* @return 返回截取的字符串
* @throws IndexOutOfBoundsException
* 抛异常情况:1.beginIndex为负;2.endIndex超出字符串总长度;3.beginIndex大于endIndex;
*/
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
//因为endIndex是开区间,所以endIndex等于字符串长度时才包含最后一个字符
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
//beginIndex从0开始且endIndex为String长度时返回本身,否则调用构造函数
return ((beginIndex == 0) && (endIndex == value.length)) ?this
: new String(value, beginIndex, subLen);
}
-
concat(String str)
:将传入String连接到源String的末尾,并返回新的一个String。
底层调用了System
类中的arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
方法。
这个方法是从src中srcPos下标开始,复制长度为length的数据到数组dest的destPos之后,此下标后的内容会被覆盖。
/**
* @param str 传入的字符串
* @return 返回的字符串,可能是本身或者新字符串
*/
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
//拿到自身的长度
int len = value.length;
//用创建一个新的char数组方式扩容,用来接收str的字符
char buf[] = Arrays.copyOf(value, len + otherLen);
//将str的字符连接到末尾
str.getChars(buf, len);
return new String(buf, true);
}
-
replace(char oldChar, char newChar)
:替换字符
/**
* 字符串替换方法,将字符串中的所有oldChar替换成newChar
* 如果字符串中不包含oldChar就返回本身
*
* @param oldChar 被替换的字符
* @param newChar 新字符
* @return 返回一个新String
*/
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;
int i = -1;
char[] val = value;
//i为oldChar第一次出现的下标
while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
//如果while有没有找到oldChar,不进入这个if
if (i < len) {
char buf[] = new char[len];
//复制下标i之前的内容
for (int j = 0; j < i; j++) {
buf[j] = val[j];
}
//复制i及之后的内容,并将所有oldChar替换成newChar
while (i < len) {
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new String(buf, true);
}
}
return this;
}
网友评论