1. 背景
String的split方法在项目中使用很广泛,但是这里面其实有些坑,截取的字段数目可能不是想要的,本文阐述这些内容,增加记性。
2. split方法介绍
首先可以看下javadoc中关于split的介绍。
String [] split(String regex)
Splits this string around matches of the given [regular expression](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#sum).
String[] split(String regex, int limit)
Splits this string around matches of the given [regular expression](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#sum).
简而言之,split方法就是根据输入的正则表达式分割字符串。
那么这又有什么毛病咧,别急。
3. split的limit参数
在项目中,经常被使用的就是第一个方法,输入一个参数regex(其实limit为0),仔细看下官方的描述
This method works as if by invoking the two-argument [`split`](https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split(java.lang.String,%20int)) method with the given expression and a limit argument of zero. Trailing empty strings are therefore not included in the resulting array.
该方法会导致后面的空串被去掉,比如
“beijing:and:shenzhen:”, 用:分割后,得到的结果为{ "beijing", "and", "shenzhen" },而有时项目是希望得到4个字段的,会造成线上严重问题。
4. split的regex参数
该参数是个正则表达式,那么要记住,在传入正则表达式的特殊字符时,可能会出呼意料的结果,要加上转义字符。比如
“beijing|and|shenzhen”, 用"//|"分割后,得到的结果为{ "beijing", "and", "shenzhen" },而有时项目是希望得到4个字段的,会造成线上严重问题。
具体有哪些特殊字符,看下split的源码介绍。
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))
{
...
}
if条件判断里面是重点,主要分为两个部分:
- 单字符的字符串并且该字符不是为正则中的特殊字符,比如.$|()[{^?*+\
(regex.value.length == 1 &&
".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1)
- 两个字符的字符串,第一个字符为转义字符(\),第二个字符非数字或这字母,其实就是将特殊字符作为分割符号。
(((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)
在这里需要指出的是,此处判断为非数字或字母采用了或(|)的位运算,很巧妙。