先说题后感:程序员这一行,很多时候,自驱学习能力是自我成长一个很重要的因素(当然技术最好的学习途径都是通过项目实践去学习、理解、掌握)。而自学方法中,除了看官方文档、技术博客等途径之外,学习源码也是一个很重要很重要的手段,在这方面,自己还需多努力。
最近有幸参加了某大厂(自己水平不够,不好意思出名字)的一次电话面试,其中一个就是现场编写代码实现
Java
中String
的IndexOf
功能。
当时想法思路是有的,但是突然从电话面试转到现场编程,思维有点懵有点紧张,最后没写出来。后来面试结束后不甘心,自己冷静的思考了下又重新做了这道题目:
实现方案一如下:
public static int IndexOf(String src, String dst) throws Exception{
if(null == src || src.length() < 1 || null == dst || dst.length() < 1){
return -1;
}
if(dst.length() > src.length()){
return -1;
}
char[] srcArray = src.toCharArray();
char[] dstArray = dst.toCharArray();
int srcLen = srcArray.length;
int dstLen = dstArray.length;
for(int i = 0; i < srcLen; i++){
boolean find = false;
if(srcArray[i] == dstArray[0] && (i+dstLen <= srcLen)){
int equalCount = 0;
for (int j = 0; j < dstLen; j++){
if(srcArray[i+j] == dstArray[j]){
equalCount++;
}
}
if(equalCount == dstLen){
find = true;
}
}
if(find){
return i;
}
}
return -1;
}
实现方案二(可能有点投机取巧了,不过相对方案一可能会耗更多的内存空间):
public static int IndexOfStr(String src, String dst) throws Exception{
if(null == src || src.length() < 1 || null == dst || dst.length() < 1 || src.length() < dst.length()){
return -1;
}
if(src.equals(dst)){
return 0;
}
int srcLen = src.length();
int dstLen = dst.length();
char[] srcArray = src.toCharArray();
char[] dstArray = dst.toCharArray();
for (int i = 0; i < srcLen; i++){
if (srcArray[i] == dstArray[0] && (i + dstLen) <= srcLen){
// 这里的substring是new新的String空间来存储
String tmpS = src.substring(i, i + dstLen);
if (tmpS.equals(dst)){
return i;
}
}
}
return -1;
}
感觉这两个实现还是有点麻烦,我们看下String的源码是如何实现的:
// 1、入口
public int indexOf(String str) {
return indexOf(str, 0);
}
// 2、调用下面的:
public int indexOf(String str, int fromIndex) {
return indexOf(value, 0, value.length,
str.value, 0, str.value.length, fromIndex);
}
// 3、最终调用:
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) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
char first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first);
}
/* Found first character, now look at the rest of v2 */
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) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}
从上面的源码可以看到,String内置的IndexOf方法,是直接对其char[]类型的私有变量value去比较的:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
......
......
}
并且String公开的返回char[] 的方法只有toCharArray,所以我们自己实现的话只能是调用这个方法得到字符数组,或者直接通过charAt(int index) 获得当前位置的字符。
而源码实现更精简的地方就是对于原字符串,在for循环里面先通过while循环一直查找到当前字符跟目标字符串的首个字符相等的位置,再开始逐个比较后面的字符是否都相等。