java基础---->String中的split方法的原理

  这里面主要介绍一下关于String类中的split方法的使用以及原理。

split函数的说明

split函数java docs的说明:

When there is a positive-width match at the beginning of this string then an empty leading substring is included at the beginning of the resulting array.A zero-width match at the beginning however never produces such empty leading substring.

The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. If the limit n is greater than zero then the pattern will be applied at most n - 1 times, the array‘s length will be no greater than n, and the array‘s last entry will contain all input beyond the last matched delimiter. If n is non-positive then the pattern will be applied as many times as possible and the array can have any length. If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded.

split函数的工作原理大概可以分为以下的几步:

1、遍历查找到regex,把regex前面到上一次的位置中间部分添加到list。这是split函数的核心部分
2、如果没有找到,则返回自身的一维数组
3、是否添加剩余的内容到list中
4、是否去除list里面的空字符串
5、从上面的list里面返回成数组

对于split函数limit的值可能会出现以下的几种情况:

1、Limit < 0, e.g. limit = -1
2、limit = 0,不传默认是0
3、Limit > 0,e.g. limit = 3
4、limit > size,e.g. limit = 20 

split函数的原理

我们通过以下的例子来分析一下split函数的原理。

public void test() {
    String string = "linux---abc-linux-";
    splitStringWithLimit(string, -1);
    splitStringWithLimit(string, 0);
    splitStringWithLimit(string, 3);
    splitStringWithLimit(string, 20);
}

public void splitStringWithLimit(String string, int limit) {
    String[] arrays = string.split("-", limit);
    String result = MessageFormat.format("arrays={0}, length={1}", Arrays.toString(arrays), arrays.length);
    System.out.println(result);
}

// arrays=[linux, , , abc, linux, ], length=6
// arrays=[linux, , , abc, linux], length=5
// arrays=[linux, , -abc-linux-], length=3
// arrays=[linux, , , abc, linux, ], length=6

一、关于第一步的操作,分为两个分支。

1、如果regex是正则表达式的元字符:".$|()[{^?*+\\”,或者regex是以\开头,以不是0-9, a-z, A-Z结尾的双字符。

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))

使用index函数查找regex的位置,维护两个下标变量。off表示上一次查找的位置(第一次off是0),next是本次查找的位置。每次查找之后把off到next中间的内容添加到list中。最后更新off的值为next+1。以供下一次的查找。

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

2、如果regex不满足上面的判断,比如说是长度大于2的字符。

return Pattern.compile(regex).split(this, limit);

使用正则表达式的mather函数,查找到regex的位置。维护着index变量,相当于上述的off。而matcher查找到的m.start()则相当于上述的next。每次查找之后把index到m.start()中间的内容添加到list中。最后更新off的值为m.end()。以供下一次的查找。

 1 public String[] split(CharSequence input, int limit) {
 2     int index = 0;
 3     boolean matchLimited = limit > 0;
 4     ArrayList<String> matchList = new ArrayList<>();
 5     Matcher m = matcher(input);
 6
 7     // Add segments before each match found
 8     while(m.find()) {
 9         if (!matchLimited || matchList.size() < limit - 1) {
10             if (index == 0 && index == m.start() && m.start() == m.end()) {
11                 // no empty leading substring included for zero-width match
12                 // at the beginning of the input char sequence.
13                 continue;
14             }
15             String match = input.subSequence(index, m.start()).toString();
16             matchList.add(match);
17             index = m.end();
18         } else if (matchList.size() == limit - 1) { // last one
19             String match = input.subSequence(index,
20                                                 input.length()).toString();
21             matchList.add(match);
22             index = m.end();
23         }
24     }
25
26     // If no match was found, return this
27     if (index == 0)
28         return new String[] {input.toString()};
29
30     // Add remaining segment
31     if (!matchLimited || matchList.size() < limit)
32         matchList.add(input.subSequence(index, input.length()).toString());
33
34     // Construct result
35     int resultSize = matchList.size();
36     if (limit == 0)
37         while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
38             resultSize--;
39     String[] result = new String[resultSize];
40     return matchList.subList(0, resultSize).toArray(result);
41 }

二、关于第二步:

如果off为0,也就是没有找到regex。直接返回自身的一维数组。

三、关于第三步:

如果limit <= 0或者list的长度还没有达到我们设置的Limit数值。那么就把剩下的内容(最后的一个regex位置到末尾)添加到list中。

四、关于第四步

这里针对的是limit等于0的处理。如果limit=0,那么会把会从后向前遍历list的内容。去除空的字符串(中间出现的空字符串不会移除) 。

五、关于第五步

调用List里面的toArray方法,返回数组。

友情链接

原文地址:https://www.cnblogs.com/huhx/p/baseusejavastringsplit.html

时间: 2024-10-07 05:18:40

java基础---->String中的split方法的原理的相关文章

Java的String中的subString()方法

public String substring(int beginIndex, int endIndex) 第一个int为开始的索引,对应String数字中的开始位置, 第二个是截止的索引位置,对应String中的结束位置 1.取得的字符串长度为:endIndex - beginIndex; 2.从beginIndex开始取,到endIndex结束,从0开始数,其中不包括endIndex位置的字符 如: "hamburger".substring(4, 8) returns "

JAVA基础 String包装类下 .replace方法的使用以及char和字符序列的使用场景

ptLink0.setText(arbu.getPtLink().replace("&","&")); // 如果像 '&','&' 这样替换是不行的,因为 '' 是给char用的,要替换字符序列的话,需要用 "" .replace连用用来替换多个char字符或者字符序列(String): // 在读取的时候,解析器会自动将其转换回"&","<","&

PL/SQL实现JAVA中的split()方法的小例子

众所周知,java中为String类提供了split()字符串分割的方法,所以很容易将字符串以指定的符号分割为一个字符串数组.但是在pl/sql中并没有提供像java中的split()方法,所以要想在pl/sql中实现字符串的分割还需要自己动手.由于在项目中需要用到此类方法,所以自己研究了一下,方便以后参考.这里以逗号作为分隔符为例,代码如下: 1 declare 2 v_str varchar2(200) := 'abd,324,u78,23f,sd09,2345,dsaf,9079'; 3

Java基础String的方法

Java基础String的方法 字符串类型写法格式如下: 格式一: String 变量名称; 变量名称=赋值(自定义或传入的变量值); 格式二: String 变量名称=赋值(自定义或传入的变量值);在输出时任何数据类型与字符串进行拼接,结果一般是字符串 1 public class StringFunc { 2 3 public static void main(String[] args){ 4 //字符串拼接 5 String str1; 6 str1 = "hello"; 7

java.lang.String 类的所有方法

java.lang.String 类的所有方法 方法摘要 char charAt(int index) 返回指定索引处的 char 值. int codePointAt(int index) 返回指定索引处的字符(Unicode 代码点). int codePointBefore(int index) 返回指定索引之前的字符(Unicode 代码点). int codePointCount(int beginIndex, int endIndex) 返回此 String 的指定文本范围中的 Un

向Java枚举类型中添加新方法

除了不能继承enum之外,可将其看做一个常规类.甚至可以有main方法. 注意:必须先定义enum实例,实例的最后有一个分号. 下面是一个例子:返回对实例自身的描述,而非默认的toString返回枚举实例的名字. public enum Color { RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4); // 成员变量 private String nam

Java基础学习中一些词语和语句的使用

在Java基础学习中,我们刚接触Java会遇到一些词和语句的使用不清的情况,不能很清楚的理解它的运行效果会是怎么样的,如:break,continue在程序中运行效果及跳转位置, 1.先来看看break和continue使用和运行效果的额说明: break:关键字,可以用于任何循环体控制结构,在循环体内执行时,当执行到break时循环会立即终止,并跳到此循环体以后的语句执行. 列如:输出0--10的数当输出到第六位时就不在继续输出了,即是跳出for循环执行for循环体以后的一句. public

java.lang.String里面的trim()方法——删除首尾空格

结果如图 package com.softeasy.test1; public class String_trim { public static void main(String[] args) { String str = " slkjfsj sdfjf jsjs "; System.out.println("没有用trim()方法前str为:|" + str + "|"); str = str.trim(); System.out.prin

String中的split(&quot;,&quot;)和split(&quot;,&quot;,-1)的区别

String中的split(",")和split(",",-1)的区别 1.当字符串最后一位有值时,两者没有区别 2.当字符串最后一位或者N位是分隔符时,前者不会继续切分,而后者继续切分.即前者不保留null值,后者保留. 举例: package stringsplit;public class stringSplit {     public static void main(String[] args) {          String line = &quo