美文网首页
String源码笔记

String源码笔记

作者: 1iangcc | 来源:发表于2018-05-18 09:13 被阅读0次
    • 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;
        }
    



    • 各种重载的valueOf()方法:
    1. 对于Object,调用Object的toString()
    2. 对于char和char[],返回一个新的String。
    3. 对于各种数字包装类,调用包装类中带参数的的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;
        }
    

    相关文章

      网友评论

          本文标题:String源码笔记

          本文链接:https://www.haomeiwen.com/subject/eqofdftx.html