JAVA中String的split⽅法
以下源码版本:JDK1.8
简介
Java 中 String 的 split ⽅法可以将字符串根据指定的间隔进⾏切割,例如字符串 str = “1,23,4,5” 经过 str.split(",") 切割后得到的返回值是⼀个字符串数组 String[] = [1, 23, 4, , 5],这种处理⽅式可以适配⼤多数场景。
问题
今天写⼀个读取csv⽂件的时候,发现⼀个⼩问题。【csv,⼀种⽂本⽂件格式,每⾏中的数据以逗号分隔,在windows平台可以使⽤excel 打开,打开后和普通excel显⽰并⽆差别】
我处理的⽂件中存在这样的⼀⾏数据:
,,,,f02e843b-a328-4023-bbbd-7ce075a29bef,,,2.00422E+19,,3000,12,6,2020/10/22,1,245.05,56.34,0,301.39,245.05,56.34,0,0,301.39,0,0,0,0,,0,0,NULL,,,, ,,,,,,,,,,,,,,,,
使⽤adLine()去读取⼀⾏,然后⽤逗号分隔:str.split(","),最后发现拿到 的字符串数组中,前⾯的空串数据存在,后⾯的空串数据都消失了。即split切割后剩下的数据:
,,,,f02e843b-a328-4023-bbbd-7ce075a29bef,,,2.00422E+19,,3000,12,6,2020/10/22,1,245.05,56.34,0,301.39,245.05,56.34,0,0,301.39,0,0,0,0,,0,0,NULL (后⾯的空串没了,到NULL结束了)
由于csv⽂件中,每列数据都对应的有key,例如第⼀列为id,第⼆列为name,等等,所以即使是空串也必须存在,不能丢失。
分析
在看过split源码后发现,String的split⽅法有两个重载⽅法:public String[] split(String regex) 和 public String[] split(String regex, int limit)
⽽调⽤split(String regex)⽅法时,内部是直接调⽤的 split(regex, 0),如下图:
在split(regex, 0)中,进⾏字符串的切割。
源码⾥,切割后⼜做了其他事情,如下:
int resultSize = list.size();
if(limit ==0){
while(resultSize >0&& (resultSize -1).length()==0){
resultSize--;
}
}
其中list储存结果数据。
如果我们使⽤split(regex)的话,会调⽤split(regex,0)那么就是说我们不传⼊limit参数,limit默认为0。所以这⾥会进⼊if语句。
进⼊后,就开始从后向前循环(resultSize为结果元素长度,所以是从后向前),如果是空串(length==0),就清除掉此数据(resultSize–)。
注意由于这⾥是 && 符号连接,所以当循环时遇到不为空串,就⽴即跳出while了。所以此过程清除掉的数据是结尾处的所有空串。
,,,a,bss,cas,,fq,try,,h,,,, 这个字符串使⽤split(",")切割后,留下的数据是,,,a,bss,cas,,fq,try,,h,在从后向前循环时碰到第⼀个不为空串的数据 h 就会停⽌,然后返回。
⽽我们想要让split不清除数据,拿到分隔后的原始数据时怎么办呢?看代码知道应该传⼊limit,让limit!=0,这样就不会进⼊if语句,不会执⾏这些清除空串数据的代码。那么limit的值应该传⼊什么呢?下⾯进⾏⼏个⼩实验:
# 1、
String str =",,,a,bss,cas,,fq,try,,h,,,,";
String[] split2 = str.split(",",1); # limit为1
System.out.String(split2));
System.out.println("长度为"+split2.length);
>[,,,a,bss,cas,,fq,try,,h,,,,] # 此处是⼀个串
>长度为1
# 2、
String str =",,,a,bss,cas,,fq,try,,h,,,,";java中split的用法
String[] split2 = str.split(",",5); # limit为5
System.out.String(split2));
System.out.println("长度为"+split2.length);
>[,,, a, bss,cas,,fq,try,,h,,,,] # 此处是5个串,分别为:空串,空串,空串,a,bss,cas,,fq,try,,h,,,,
>长度为5
# 3、
String str =",,,a,bss,cas,,fq,try,,h,,,,";
String[] split2 = str.split(",", Integer.MAX_VALUE); # limit为Integer.MAX_VALUE
System.out.String(split2));
System.out.println("长度为"+split2.length);
>[,,, a, bss, cas,, fq,try,, h,,,,] # 此处将所有串都拿到了,没有清除数据。
>长度为15
当传⼊负数时,偶尔会运⾏成功,⼤多数情况下,会报以下错误:
结论
我们可以分析出,传⼊limit为正数时,split就不会帮我们清除掉它认为⽆⽤的数据,⽽是将limit作为结果长度的最⼤值进⾏切割。⽽当传⼊limit为0时,split会帮我们切割掉后⾯的空串。所以limit的含义是切割后结果的阀值(最⼤值),帮我们限制切割后结果的长度,limit为0时就⾛JAVA⾃⼰定的规则(清除结尾处的空串)。
所以当我们的使⽤场景需要全部数据时,要使⽤两个参数的split⽅法⼿动传⼊limit,建议limit的值为Integer.MAX_VALUE,这样可以在不知道结果长度的情况下保证结果正确。
split(regex,limit)⽅法的完整结构⼤概可分三段解释,如图:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。