这里面主要介绍一下关于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 -  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函数的工作原理大概可以分为以下的几步:

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

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

、Limit < , e.g. limit = -
、limit = ,不传默认是0
、Limit > ,e.g. limit =
、limit > size,e.g. limit =

split函数的原理

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

public void test() {
String string = "linux---abc-linux-";
splitStringWithLimit(string, -);
splitStringWithLimit(string, );
splitStringWithLimit(string, );
splitStringWithLimit(string, );
} 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 ==  &&
".$|()[{^?*+\\".indexOf(ch = regex.charAt()) == -) ||
(regex.length() == &&
regex.charAt() == '\\' &&
(((ch = regex.charAt())-'')|(''-ch)) < &&
((ch-'a')|('z'-ch)) < &&
((ch-'A')|('Z'-ch)) < )) &&
(ch < Character.MIN_HIGH_SURROGATE ||
ch > Character.MAX_LOW_SURROGATE))
使用index函数查找regex的位置,维护两个下标变量。off表示上一次查找的位置(第一次off是0),next是本次查找的位置。每次查找之后把off到next中间的内容添加到list中。最后更新off的值为next+1。以供下一次的查找。
{
int off = ;
int next = ;
boolean limited = limit > ;
ArrayList<String> list = new ArrayList<>();
while ((next = indexOf(ch, off)) != -) {
if (!limited || list.size() < limit - ) {
list.add(substring(off, next));
off = next + ;
} 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 == )
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 == ) {
while (resultSize > && list.get(resultSize - ).length() == ) {
resultSize--;
}
}
String[] result = new String[resultSize];
return list.subList(, 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()。以供下一次的查找。

 public String[] split(CharSequence input, int limit) {
int index = ;
boolean matchLimited = limit > ;
ArrayList<String> matchList = new ArrayList<>();
Matcher m = matcher(input); // Add segments before each match found
while(m.find()) {
if (!matchLimited || matchList.size() < limit - ) {
if (index == && index == m.start() && m.start() == m.end()) {
// no empty leading substring included for zero-width match
// at the beginning of the input char sequence.
continue;
}
String match = input.subSequence(index, m.start()).toString();
matchList.add(match);
index = m.end();
} else if (matchList.size() == limit - ) { // last one
String match = input.subSequence(index,
input.length()).toString();
matchList.add(match);
index = m.end();
}
} // If no match was found, return this
if (index == )
return new String[] {input.toString()}; // Add remaining segment
if (!matchLimited || matchList.size() < limit)
matchList.add(input.subSequence(index, input.length()).toString()); // Construct result
int resultSize = matchList.size();
if (limit == )
while (resultSize > && matchList.get(resultSize-).equals(""))
resultSize--;
String[] result = new String[resultSize];
return matchList.subList(, resultSize).toArray(result);
}

二、关于第二步:

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

三、关于第三步:

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

四、关于第四步

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

五、关于第五步

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

友情链接

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

  1. java基础---->String中replace和replaceAll方法

    这里面我们分析一下replace与replaceAll方法的差异以及原理. replace各个方法的定义 一.replaceFirst方法 public String replaceFirst(Str ...

  2. java.lang.String中的replace方法到底替换了一个还是全部替换了。

    你没有看错我说的就是那个最常用的java.lang.String,String可以说在Java中使用量最广泛的类了. 但是我却发现我弄错了他的一个API(也可以说是两个API),这个API是关于字符串 ...

  3. Java的String中的subString()方法

    方法如下: public String substring(int beginIndex, int endIndex) 第一个int为开始的索引,对应String数字中的开始位置, 第二个是截止的索引 ...

  4. java.lang.String中的trim()方法的详细说明(转)

    String.Trim()方法到底为我们做了什么,仅仅是去除字符串两端的空格吗? 一直以为Trim()方法就是把字符串两端的空格字符给删去,其实我错了,而且错的比较离谱. 首先我直接反编译String ...

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

    众所周知,java中为String类提供了split()字符串分割的方法,所以很容易将字符串以指定的符号分割为一个字符串数组.但是在pl/sql中并没有提供像java中的split()方法,所以要想在 ...

  6. Java基础String的方法

    Java基础String的方法 字符串类型写法格式如下: 格式一: String 变量名称; 变量名称=赋值(自定义或传入的变量值); 格式二: String 变量名称=赋值(自定义或传入的变量值); ...

  7. java.lang.String 类的所有方法

    java.lang.String 类的所有方法 方法摘要 char charAt(int index) 返回指定索引处的 char 值. int codePointAt(int index) 返回指定 ...

  8. 2017.10.28 针对Java Web应用中错误异常处理方法的运用

    针对Java Web应用中错误异常处理方法的运用 在javaweb中其异常都需要对Checked Exception之下的Exception进行继承,并且有选择地对发生的错误和异常进行处理.Java同 ...

  9. Java基础关于Map(字典)的方法使用

    Java基础关于Map(字典)的方法使用 java中一般用map与hashmap来创建一个key-value对象 使用前提是要导入方法包: import java.util.HashMap: impo ...

随机推荐

  1. C#_02.14_基础五_.NET类

    C#_02.14_基础五_.NET类 一.类实例: 我们前面说过类是一个模板,我们通过类创建一个又一个的实例,通常情况下类当中的变量是每一个实例都各有一份的,互相不影响,而静态字段是除外的,静态字段是 ...

  2. MySql的优化步骤

    MySql优化的一般步骤: 1.通过show status 命令了解各种sql的执行效率 SHOW STATUS提供msyql服务器的状态信息 一般情况下,我们只需要了解以”Com”开头的指令 sho ...

  3. Android CollapsingToolbarLayout使用介绍

    我非常喜欢Material Design里折叠工具栏的效果,bilibili Android客户端视频详情页就是采用的这种设计.这篇文章的第二部分我们就通过简单的模仿bilibili视频详情页的实现来 ...

  4. 初识Vulkan【转】

    Vulkan是Khronos组织制定的“下一代”开放的图形显示API.是与DirectX12能够匹敌的GPU API标准. Vulkan是基于AMD的Mantle API演化而来,眼下Vulkan 1 ...

  5. 转: ffmpeg循环推流方法

    from:  https://blog.csdn.net/weiyuefei/article/details/64125208 ffmpeg循环推流方法 You should be able to u ...

  6. JavaWeb开发的一些问题

    从今天开始,在此帖陆续会记录一些平时所遇到的一些问题 1.20181229 org.apache.ibatis.binding.BindingException: Invalid bound stat ...

  7. Python之Simple FTP (一)

    一.引言: 好久之前想写一个ftpserver的小daemon,但是一直拖着就没有写,这回正好处于放假的时候可以有时间来写写. 二.FTP需求功能: 1.用户认证系统 2.文件上传和下载功能 a.支持 ...

  8. 免费ss账号网站

    下面网址按排序顺序优先使用,数字越小优先级越高 1,https://io.freess.today/ 2,https://free-ss.site/ 3,https://ss.freess.org/ ...

  9. Spring Boot系列——AOP配自定义注解的最佳实践

    AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一. 首先,我声明下,我不是来系统介绍什么是AOP,更不是照本宣科讲解什么是连接点.切面. ...

  10. 谈谈tmpdir与innodb_tmpdir的区别和用处

    [背景] innodb_tmpdir是在innodb online ddl中提到的一个参数:大致的意思是innodb在做online-ddl的时候会向临时目录写入“临时排序文件” 而这些文件的大小基本 ...