共同学习Java源码--常用数据类型--String(十四)

 public String[] split(String regex, int limit) {
        /* fastpath if the regex is a  (1)one-char String and this character is not one of the  RegEx's meta characters ".$|()[{^?*+\\", or  (2)two-char String and the first char is the backslash and  the second is not the ascii digit or ascii letter.  */
        char ch = 0;
        if (((regex.value.length == 1 &&
             ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
             (regex.length() == 2 &&
              regex.charAt(0) == '\\' &&
              (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
              ((ch-'a')|('z'-ch)) < 0 &&
              ((ch-'A')|('Z'-ch)) < 0)) &&
            (ch < Character.MIN_HIGH_SURROGATE ||
             ch > Character.MAX_LOW_SURROGATE))
        {
            int off = 0;
            int next = 0;
            boolean limited = limit > 0;
            ArrayList<String> list = new ArrayList<>();
            while ((next = indexOf(ch, off)) != -1) {
                if (!limited || list.size() < limit - 1) {
                    list.add(substring(off, next));
                    off = next + 1;
                } else {    // last one                     //assert (list.size() == limit - 1);                     list.add(substring(off, value.length));
                    off = value.length;
                    break;
                }
            }
            // If no match was found, return this             if (off == 0)
                return new String[]{this};


            // Add remaining segment             if (!limited || list.size() < limit)
                list.add(substring(off, value.length));


            // Construct result             int resultSize = list.size();
            if (limit == 0) {
                while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
                    resultSize--;
                }
            }
            String[] result = new String[resultSize];
            return list.subList(0, resultSize).toArray(result);
        }
        return Pattern.compile(regex).split(this, limit);
    }

    public String[] split(String regex) {
        return split(regex, 0);
    }

这两个方法一起看,是将本字符串以正则表达式为规则,将字符串内容打散成数组的方法。

第一个方法首先定义char变量ch初始值为0,然后进入一个很复杂的if表达式,其实把格式整理好了就容易看了。

        if (
        (
        (regex.value.length == 1 && ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) 
         ||
                (
         regex.length() == 2 && regex.charAt(0) == '\\' 
         && (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 
         && ((ch-'a')|('z'-ch)) < 0 
         && ((ch-'A')|('Z'-ch)) < 0
        )
        ) 
        &&
        (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE)
          )

先看最下方那个&& 右边是判断ch在D800和DFFF之间。

最下方那个&&左边是一个||连接的两个表达式。

||左边是判断regex变量长度为1,且不含正则表达式基本元素(.$|()[{^?),说白了就是判断是一个字符且不是正则表达式。

||右边是在判断regex变量长度为2,且第一个字符是”\”,也就是转义字符。后面是用|来判断regex不属于0-9A-Za-z这个区间的字符,|是判断二进制里每一位只要有一个是1,那么最后结果的二进制相应位就是1。

这个if判断的是非正则表达式,如果regex为正则表达式,直接调用Pattern类的方法来处理,此处不做详谈。

然后定义变量off,初始值为0,也就是搜索的初始下标。定义变量next也就是每个regex里。

定义一个ArrayList。

进入while循环,在本字符串里不停地搜索ch的下标,只要ch的下标不是-1。ch此时可能是原来regex的第一个或第二个字符。

如果是从第二个方法调用的,那么limit是0,limited就是false,off初始值是0。进入if中将off到这个元素下标位置的所有元素截取成新字符串加入到list中,不断往复,off会移动到next下标的右侧。

如果limit不为0且limit-1大于等于ArrayList的长度,那么进入else中,这里就截取off之后的所有字符串放入list中。else的成立条件推测是limit要大于0。

跳出循环后off还是0.说明没有搜索到,直接返回本字符串,将本字符串放入一个String数组中。

接下来是将off的最后取值之后的元素放入list中。然后获取这个ArrayList的长度,接下来处理的是ArrayList最后一个元素是不是空字符串,如果是,则记录ArrayList长度的变量resultSize减一,其实这种方式法去掉结果中间的空串。

最后构建字符串数组,用list的相关方法生成数组返回。

第二个方法就是调用第一个方法,并将limit传入0。

    原文作者:分享你刚编的故事
    原文地址: https://zhuanlan.zhihu.com/p/46622167
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞