java String 源码分析<四> 常用方法分析indexOf方法分析

indexOf(int ch, int fromIndex) 方法

indexOf(int ch, int fromIndex) 方法
indexOf(int ch) 方法

 /**
     * 
     * @param   ch   一个字符
     * @return   从0索引开始第一次出现ch字符的索引
     */
   public int indexOf(int ch) {
        return indexOf(ch, 0);
    }
     /**
     * 
     * @param   ch   一个字符
     * @param   fromIndex 开始搜索的索引
     * @return   从fromIndex索引开始第一次出现ch字符的索引
     */
     public int indexOf(int ch, int fromIndex) {
     //获取当前对象字符串的长度
        final int max = value.length;
        //如果索引fromIndex<0则重置为0
        if (fromIndex < 0) {
            fromIndex = 0;
        } else if (fromIndex >= max) {
            //如果从索引fromIndex大于等于字符串的长度
            //则说明没有找到该字符,因为已经到字符串结尾
            return -1;
        }
        // MIN_SUPPLEMENTARY_CODE_POINT = 0x010000;
//这表明在java中char存储的值通常都是比ox010000小的,就是BMP类型的字符。
//而当比这个值大的时候,就是增补字符了,那么会调用Character先判断是否是有效的字符,再进一步处理
        //一般值都小于0x010000,大于的现在不研究
        //先从简单入手
        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            
            final char[] value = this.value;
            for (int i = fromIndex; i < max; i++) {
                //从fromIndex开始递增查找
                if (value[i] == ch) {
                    return i;
                }
            }
            return -1;
        } else {
        //此处indexOfSupplementary方法的源码设计Character方面源码,此处暂不讨论。
            return indexOfSupplementary(ch, fromIndex);
        }
    }

indexOf(char[] source, int sourceOffset, int sourceCount,char[] target, int targetOffset, int targetCount,int fromIndex) 方法

 /**
     * 
     * @param   str   要搜索的子字符串。
     * @return   返回指定子字符串第一次出现的字符串内的索引。
     */
    public int indexOf(String str) {
        return indexOf(str, 0);
    }
    /**
     * @param   str  要搜索的子字符串
     * @param   fromIndex   从fromIndex开始搜索的索引。
     * @return  返回从fromIndex索引开始查找,指定子串的第一次出现在字符串中的索引
     */
      public int indexOf(String str, int fromIndex) {
        return indexOf(value, 0, value.length,
                str.value, 0, str.value.length, fromIndex);
    }
    static int indexOf(char[] source, int sourceOffset,int sourceCount,String target, int fromIndex) {
        return indexOf(source, sourceOffset, sourceCount,
                       target.value, 0, target.value.length,
                       fromIndex);
    }
    / * @param   source       源字符串的数组.
     * @param   sourceOffset  源字符串的偏移量.
     * @param   sourceCount   源字符串的长度.
     * @param   target       子串的数组.
     * @param   targetOffset 子串偏移量.
     * @param   targetCount  子串的长度
     * @param   fromIndex    开始索引的位置
     * @return 返回某个子串在当前字符串的起始位置索引
     */
    static int indexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
        //开始索引位置大于等于源字符串的长度
        if (fromIndex >= sourceCount) {
            //如果子串长度为0 ,则返回索引为 源字符串的长度的位置
            //如果子串不为0,则说明没有找到 返回-1
            return (targetCount == 0 ? sourceCount : -1);
        }
        /开始查找索引位置必须大于等于0
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        //如果子串长度为0,则返回开始索引位置fromIndex
        if (targetCount == 0) {
            return fromIndex;
        }
        
        //例如:源字符串source=abcdeabcde,源字符串偏移量sourceOffset=1,
        //则源字符串长度sourceCount =10
        //子串target=eabd,子串偏移量为targetOffset=1,
        //子串长度targetCount=4
        //开始查找位置为fromIndex=2
        //说明:
        //我们需要从源字符串source 从索引位置fromIndex=2,在偏移sourceOffset=1
        //查找(子串target偏移量为targetOffset=1后的字符串)的位置
    
        //说明子串查找的第一个字符first =target[1];因为子串偏移量是1
        //源字符 开始查找位置为sourceOffset + fromIndex
        //因为
        //子串长度为4 偏移量为1 我们只需判断字串后三个字符
        //源字符串长度为10 偏移量为1
        //所以我们只需要判断到源字符串的1+10-(4-1)=8的索引就可以了
        
        //子串的第一个字符
        char first = target[targetOffset];
        //要检索到source数组的最大索引位置
         int max = sourceOffset + (sourceCount - targetCount);
         //个人认为这里应该为:
      //int max = sourceOffset + (sourceCount - (targetCount-targetOffset));
      //因为java源码调用该indexOf方法时 sourceOffset和targetOffset都为0 所以并没影响
        
        
        
        //i表示源字符串source的第一个开始索引位置
        for (int i = sourceOffset + fromIndex; i <= max; i++) {
           //判断第一个字符是否相等
            if (source[i] != first) {
                //如果不相等则 while循环一直找到第一个字符相等的位置
                while (++i <= max && source[i] != first);
            }
            
            //此时的i变量为第一个字符相等的索引
            
            //i<max说明找到第一个字符相等的位置索引
            if (i <= max) {
             
             
              //i为第一个字母相等的索引位置
               //j表示源字符串source第二个字符
                int j = i + 1;
                //end  因为要查找到子串最后,所以计算出与子串长度相同对应的源字符串source的索引位置
                int end = j + targetCount - 1;
                //个人理解这里应该为 end = j+targetCount-targetOffset - 1;
                //源码调用此方法targetOffset都为0 所以并没有区别
                 //下面判断第二个字符至最后一个字符是否相等
                 //k表示的是子串的第二个字符索引
                 //从第二个字符判断是否相等 for循环一直到最后
                for (int k = targetOffset + 1; j < end && source[j]
                        == target[k]; j++, k++);
                //j==end 说明所有字符都相等
                if (j == end) {
                    //此时i是第一个字符相等的索引,需要减去偏移量
                    return i - sourceOffset;
                }
                //没有找到说明第一个字符相等的索引位置i不成立
                //应该继续向后继续查找第一个位置字符相等的索引
                
                
            }
        }
        return -1;
    }

下面为小编的测试
indexOf为String的源码的拷贝
indexOfModify为小编修改的源码

public class Test {
    public static void main(String[] args) {
         String s = "abcdeabcde";
         String t = "ebcde";
         char[] source = s.toCharArray();
        char[] target = t.toCharArray();
        //调用string indexOf的源码 sourceOffset 和targetOffset 只能是0
        //
        int a =  indexOf(source,0,s.length(),
                target,0,t.length(),0);
        System.out.println("a="+a);//-1
        int b =  indexOfModify(source,0,s.length(),
                target,1,t.length(),0);
        System.out.println("b="+b);//1

        int c =  indexOfModify(source,1,s.length(),
                target,1,t.length(),0);
        System.out.println("c="+c);//0

        int d =  indexOfModify(source,1,s.length(),
                target,1,t.length(),2);
        System.out.println("d="+d);//5




        String s1 = "abfcdeabcde";
        String t1 = "febcde";

        char[] source1 = s1.toCharArray();
        char[] target1 = t1.toCharArray();
        int e =  indexOfModify(source1,0,s1.length(),
                target1,0,t1.length(),0);
        System.out.println("e="+e);//-1

        int f =  indexOfModify(source1,1,s1.length(),
                target1,2,t1.length(),0);
        System.out.println("f="+f);//6

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

    static int indexOfModify(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-targetOffset));
        //这里修改了max

        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-targetOffset - 1;
                //这里修改了end
                for (int k = targetOffset + 1; j < end && source[j]
                        == target[k]; j++, k++);

                if (j == end) {
                    /* Found whole string. */
                    return i - sourceOffset;
                }
            }
        }
        return -1;
    }

}

输出结果

a=-1
b=1
c=0
d=5
e=-1
f=6
文章参考转载:
http://www.516tool.com/java/28.html

后续请看

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。