请问下列代码输出结果是什么?(文章结尾会告诉答案)
private static final String REGEX = ";";
public static void main(String[] args) throws Exception {
split("");
split(";");
split(";", -1);
split("1;;");
split("1;;",-1);
split("1;;1");
}
private static void split(String str) {
split(str, 0);
}
private static void split(String str, int limit) {
print(str.split(REGEX, limit), str);
}
private static void print(String[] arr, String str) {
System.out.println(String.format("%s分隔后数组的长度=%s", str, arr.length));
System.out.println(String.format("%s分隔后的数组内容为=%s", str, Arrays.toString(arr)));
System.out.println("==================");
}
要了解代码背后的原因,阅读源码是一种非常有效的方式。
String类的split()方法有两个重载的方法,这两个方法是
public String[] split(String regex) {
return split(regex, 0);
}
public String[] split(String regex, int limit) {
// 一大推代码
}
可以看到这个split()方法有两个参数,第一个参数是我们分隔的字符串的分隔符,第二个参数很奇怪哦,所以我们看一下源码是怎样解释的。
为了更好的说明上面英文的意思,我们以字符串"1;;1;",分隔为;为例。首先从我们意识里来说这段字符串可以被分隔成4段(分隔符的数量+1),也就是说n=4
limit | 数组长度 | 说明 |
---|---|---|
limit<0 | 4=n | 返回n长度的数组 |
limit=0 | 3<=n | 最后面的空字符串将被截取掉 |
0<limit<=n | limit<=n | 返回的数组长度等于limit |
limit>n | 4=n | 返回的数组长度等于n |
其中limit=0的情况就是默认情况public String[] split(String regex)。
接下来我们看一下源码部分:
public String[] split(String regex, int limit) {
// 这里的意思是说对于简单的regex就在这里判断了
/* 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))
{
// 截取代码部分
}
// 走正则表达式的部分,主要逻辑和截取代码部分相同
return Pattern.compile(regex).split(this, limit);
}
下面我们重点关注截取部分的代码:
相信,至此你已经能够正确解答本文开头的例子了。
开头问题参考答案
字符串处理利器Guava
最后补充一个goole公司开发的java工具包Guava,里面有一些非常实用的字符串处理工具。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
其中关于字符串的拆分的示例代码如下:
// 拆分方式 忽略空的字符串 对截取的字符串做trim()
List<String> split1 = Splitter.on(",").omitEmptyStrings().trimResults().splitToList("2,,3 ,4");
List<String> split2 = Splitter.on(",").omitEmptyStrings().trimResults().splitToList("2,,3 ,4,,");
List<String> split3 = Splitter.on(",").omitEmptyStrings().trimResults().splitToList("");
System.out.println(String.format("长度=%s,内容=%s", split1.size(), split1));// 长度=3,内容=[2, 3, 4]
System.out.println(String.format("长度=%s,内容=%s", split2.size(), split2));// 长度=3,内容=[2, 3, 4]
System.out.println(String.format("长度=%s,内容=%s", split3.size(), split3));// 长度=0,内容=[]
关于Guava的更多实用方法可以参考 Guava用法总结