今天在做leetcode上的题目时,用到了字符串中的split函数,但切出来的数组含有空字符串 "",迫于知道什么原因,跑去看了一下源码,结果一早上就过去了,记录一下。
测试字符串:"a,,a,,b,c,,c"
当对该字符串使用split(",")时,结果如下:(其中的空字符用了true代替)
那为什么会出现这种情况呢?接下来让我们去源码里面看看。
split(String regex)方法会调用其重载方法 split(String regex, int limit),直接去看它的重载方法。其中的limit形参应该是与贪婪匹配有关的,limit = 0则尽可能多地匹配,limit > 0时最多匹配limit - 1次,这不是我们讨论的重点,略过。
接下来看到 split(String regex, int limit)方法。首先,映入眼帘的是一大坨的if语句,很多人看到这里估计都跑了,我也差不多哈哈😄。别怕,其实只要把它拆开看就没那么难了。
根据官方文档的说明,这个if是判断传入的表达式 regex是否是一个长度为1的字符串,并且该字符串不包含".$|()[{^?*+\" 或者 该表达式是一个长度为2的字符串,其中,第一个字符是反斜杠且第二个字符不能是数字或者大小写字母(应该是判断表达式是否为转义符)。如果满足if条件的话,该方法就会自己解决分割,不然,只能交给Pattern类这位大哥去做了。
这里插一句,不得不说,官方写的代码就是优雅,ch这个变量的赋值工作已经在if判断中做完了,而且两种情况对应两个值。
好的,前置工作弄完以后,接下来就正式进入正题了。先把全部代码拿过来。
这里先声明了两个变量off和next。off是指定接下来截取的子字符串的起始位置,next是指向下一个regex的位置。至于limited变量,我们此次讨论的是limit = 0的情况,默认它为false就可以。
用一个列表保存切割出来的字符串。接下来进入while循环, 根据起始位置off和ch的值找到next的位置,如果找不到,则结束循环。limited始终为false,只看if,else略过。
根据off和next的位置取得子字符串,将它加入list,off变为next + 1。不能是off = next,如果这样的话下次切割的字符串会含有regex表达式中的值。重复切割,直到找不到下一个next。
这里说一下出现空字符串的原因,先说规律,如果字符串对应regex表达式中的值是连续的,每多一个连续的值,则多一个空字符串。拿 "a,,a,,b,c,,c" 举个例子
出了while循环,如果off的值还是为0,则说明没有一次切割,直接返回自身。
最后还要添加剩余的部分。分两种情况
情况一:字符串的最后一个字符不匹配regex(",")的值
还是以 "a,,a,,b,c,,c"为例
情况二:字符串的最后一个字符匹配regex(",")的值
以 "a,,a,,b,c,,c,"为例
注意到我框起来的地方,不知道大家有没有跟我一样的疑惑,off = s.length()不会越界吗???
于是,我又跑去看了substring(int beginIndex, int endIndex)的源码
a,,a,,b,c,,c,,,,,,,",这种情况列表list的末尾会出现很多的空字符串)
最后,将整理过的list转换为数组返回。