一、源码解读
做银行项目时经常有对收益、份额、清算等数据文件导入数据库操作,需要用I/O流进行数据处理。在数据处理中有步重要的操作,那就是对文件的数据进行解析。一般的数据文件采用的分割原则,统一使用“|”、“,”或者其他的约束好的分隔符进行分割。
一般通常采用String的方法split进行解析
以下是源码,通过源码发现,String中已多态的形式提供了4个方法,而split(String regex)方法只是简单的再次的调用了 split(String regex , int limit)只是默认了第二个参数limit为0;
public String[] split(String regex) {
return split(regex, 0);
}
接着调用 split(String regex,int limit)方法,源码如下:
public String[] split(String regex, int limit) {
/* 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.
译:
(1)当字符串长度为1位时,判断是否是“.$|()[{^?*+\\”即正则表达式中的元字符
(2)当字符串长度为2位时,判断第一个字符是不是反斜杠且不是数字或者字母
满足上面条件,即按照传入的字符串进行分割成数组,反之按照正则表达式的方式分割
*/
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))
{
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);
}
return Pattern.compile(regex).split(this, limit);
}
二、用法注意
上面源码中方法参数limit需要注意
1、limit为0的情况
当我们没有传入limit参数时,自动默认limit等于0。
当limit为0时,如果后几位为空字符串(只要满足长度为0)将自动舍去。
例如:
@Test
public void testSpilit() {
String oriStr = "|1|2|3|4|||";
String[] arr = oriStr.split("\\|");
}
结果:
2、limit为-1的情况
返回已分割的最大长度。
例如:
@Test
public void testSpilit() {
String oriStr = "|1|2|3|4|||";
String[] arr = oriStr.split("\\|",-1);
}
结果如下:
当limit结果为一个大于0的正整数时:
分为两种情况:
(1)当limit的值<实际分割出来的数组长度(即limit为-1时分割出来的数组长度)时,返回limit长度的数组,后几位没有分割的字符串存入数组最后一位
例如:
@Test
public void testSpilit() {
String oriStr = "|1|2|3|4|||";
String[] arr = oriStr.split("\\|",3);
结果如下:
由上面limit为-1时结果可以看到,原实际返回长度为8位。当我们limit传入3时,只返回3位长度的数组,未完成分割的,合并成一个字符串作为数组的最后一位。由上面的源码也可以看到,每进行一次分割时,都会判断当前已分割的长度是否小于limit,若不满足,则直接跳出,最后以这样的方式存入
list.add(substring(off, value.length));
off是当前未分割字符串的第一位,value.length为字符串的长度。
(2)当limit的值>=实际分割出来的数组长度,其返回结果于limit=-1时返回结果相同。
例如:
@Test
public void testSpilit() {
String oriStr = "|1|2|3|4|||";
String[] arr = oriStr.split("\\|",10);
}
结果如下: