• JDK中String类的源码分析(二)


    1、startsWith(String prefix, int toffset)方法

    包括startsWith(*),endsWith(*)方法,都是调用上述一个方法

     1     public boolean startsWith(String prefix, int toffset) {
     2         char ta[] = value;
     3         int to = toffset;
     4         char pa[] = prefix.value;
     5         int po = 0;
     6         int pc = prefix.value.length;
     7         // Note: toffset might be near -1>>>1.
     8         if ((toffset < 0) || (toffset > value.length - pc)) {
     9             return false;
    10         }
    11         while (--pc >= 0) {
    12             if (ta[to++] != pa[po++]) {
    13                 return false;
    14             }
    15         }
    16         return true;
    17     }

    上述算法的时间复杂度,最差的情况下为O(n)(取决于匹配子串的长度),最理想的情况下为O(1);

    2、indexOf方法

    有多个重载的方法,参数可以为字符,也可以为字符串

     1     static int indexOf(char[] source, int sourceOffset, int sourceCount,
     2             char[] target, int targetOffset, int targetCount,
     3             int fromIndex) {
     4         if (fromIndex >= sourceCount) {
     5             return (targetCount == 0 ? sourceCount : -1);
     6         }
     7         if (fromIndex < 0) {
     8             fromIndex = 0;
     9         }
    10         if (targetCount == 0) {
    11             return fromIndex;
    12         }
    13 
    14         char first = target[targetOffset];
    15         int max = sourceOffset + (sourceCount - targetCount);
    16 
    17         for (int i = sourceOffset + fromIndex; i <= max; i++) {
    18             /* Look for first character. */
    19             if (source[i] != first) {
    20                 while (++i <= max && source[i] != first);
    21             }
    22 
    23             /* Found first character, now look at the rest of v2 */
    24             if (i <= max) {
    25                 int j = i + 1;
    26                 int end = j + targetCount - 1;
    27                 for (int k = targetOffset + 1; j < end && source[j]
    28                         == target[k]; j++, k++);
    29 
    30                 if (j == end) {
    31                     /* Found whole string. */
    32                     return i - sourceOffset;
    33                 }
    34             }
    35         }
    36         return -1;
    37     }

    这个匹配子串的方法比较复杂,值得深入研究

    3、substring方法

    在JDK1.7之前的代码中,substring存在严重内存泄露问题,然而,这个问题在JDK1.7之后的版本中都有了改善;

    因为JDK1.7中修改了构造方法,调用Arrays.copyOfRange()方法,只是复制出数组的一部分;

    关于String类的构造方法,可以参看: JDK中String类的源码分析(一)

    4、concat方法

    连接两个字符串

     1     public String concat(String str) {
     2         int otherLen = str.length();
     3         if (otherLen == 0) {
     4             return this;
     5         }
     6         int len = value.length;
     7         char buf[] = Arrays.copyOf(value, len + otherLen);
     8         str.getChars(buf, len);
     9         return new String(buf, true);
    10     }

    5、split方法,切割字符串

     1     public String[] split(String regex, int limit) {
     2         
     3         char ch = 0;
     4         if (((regex.value.length == 1 &&
     5              ".$|()[{^?*+\".indexOf(ch = regex.charAt(0)) == -1) ||
     6              (regex.length() == 2 &&
     7               regex.charAt(0) == '\' &&
     8               (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
     9               ((ch-'a')|('z'-ch)) < 0 &&
    10               ((ch-'A')|('Z'-ch)) < 0)) &&
    11             (ch < Character.MIN_HIGH_SURROGATE ||
    12              ch > Character.MAX_LOW_SURROGATE))
    13         {
    14             int off = 0;
    15             int next = 0;
    16             boolean limited = limit > 0;
    17             ArrayList<String> list = new ArrayList<>();
    18             while ((next = indexOf(ch, off)) != -1) {
    19                 if (!limited || list.size() < limit - 1) {
    20                     list.add(substring(off, next));
    21                     off = next + 1;
    22                 } else {    // last one
    23                     //assert (list.size() == limit - 1);
    24                     list.add(substring(off, value.length));
    25                     off = value.length;
    26                     break;
    27                 }
    28             }
    29             // If no match was found, return this
    30             if (off == 0)
    31                 return new String[]{this};
    32 
    33             // Add remaining segment
    34             if (!limited || list.size() < limit)
    35                 list.add(substring(off, value.length));
    36 
    37             // Construct result
    38             int resultSize = list.size();
    39             if (limit == 0)
    40                 while (resultSize > 0 && list.get(resultSize - 1).length() == 0)
    41                     resultSize--;
    42             String[] result = new String[resultSize];
    43             return list.subList(0, resultSize).toArray(result);
    44         }
    45         return Pattern.compile(regex).split(this, limit);
    46     }

    6、trim方法,去除字符串两端的空格

     1     public String trim() {
     2         int len = value.length;
     3         int st = 0;
     4         char[] val = value;    /* avoid getfield opcode */
     5 
     6         while ((st < len) && (val[st] <= ' ')) {
     7             st++;
     8         }
     9         while ((st < len) && (val[len - 1] <= ' ')) {
    10             len--;
    11         }
    12         return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
    13     }

    算法时间复杂度在O(log(n))左右,截取,创建一个新的字符串;

    总结:

    在String类中的大多数方法,都存在new对象的操作,因为String的不可变性,如果大量的调用这些方法,在内存中会产生大量的String对象;

    这样对GC的压力很非常大,很可能会出现内存溢出;

  • 相关阅读:
    Server-Side Access Control
    MDN > Web technology for developers > HTTP
    HTML5解决跨域问题
    HTML5安全:CORS(跨域资源共享)简介
    HTML5 知识点
    android中viewPager+fragment实现的屏幕左右切换(进阶篇)
    【Android】Android 博客园客户端 (七)登录功能
    【Tools】Pro Git 一二章读书笔记
    【JavaScript】重温Javascript继承机制
    【334】Python Object-Oriented Programming
  • 原文地址:https://www.cnblogs.com/lianliang/p/5737705.html
Copyright © 2020-2023  润新知