java开发使用StringUtils.split避坑详解_第1页
java开发使用StringUtils.split避坑详解_第2页
java开发使用StringUtils.split避坑详解_第3页
java开发使用StringUtils.split避坑详解_第4页
java开发使用StringUtils.split避坑详解_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第java开发使用StringUtils.split避坑详解目录正文StringUtils.split的坑StringUtils.split源码分析如何解决?

正文

在日常的Java开发中,由于JDK未能提供足够的常用的操作类库,通常我们会引入ApacheCommonsLang工具库或者GoogleGuava工具库简化开发过程。两个类库都为java.langAPI提供了很多实用工具,比如经常使用的字符串操作,基本数值操作、时间操作、对象反射以及并发操作等。

dependency

groupIdmons/groupId

artifactIdcommons-lang3/artifactId

version3.12.0/version

/dependency

但是,最近在使用ApacheCommonsLang工具库时踩了一个坑,导致程序出现了意料之外的结果。

StringUtils.split的坑

也是因为踩了这个坑,索性写下一篇文章好好介绍下ApacheCommonsLang工具库中字符串操作相关API。

先说坑是什么,我们都知道String类中到的split方法可以分割字符串,比如字符串aabbccdd根据bc分割的结果应该是aab和cdd才对,这样的结果也很容易验证。

Stringstr="aabbccdd";

for(Strings:str.split("bc")){

System.out.println(s);

//结果

可能是因为String类中的split方法的影响,我一直以为StringUtils.split的效果应该相同,但其实完全不同,可以试着分析下面的三个方法输出结果是什么,StringUtils是CommonsLang类库中的字符串工具类。

publicstaticvoidtestA(){

Stringstr="aabbccdd";

String[]resultArray=StringUtils.split(str,"bc");

for(Strings:resultArray){

System.out.println(s);

我对上面testA方法的预期是aab和cdd,但是实际上这个方法的运行结果是:

//testA输出

aa

dd

可以看到b和c字母都不见了,只剩下了a和b,这是已经发现问题了,查看源码后发现StringUtils.split方法其实是按字符进行操作的,不会把分割字符串作为一个整体来看,返回的结果中不也会包含用于分割的字符。

验证代码:

publicstaticvoidtestB(){

Stringstr="abc";

String[]resultArray=StringUtils.split(str,"ac");

for(Strings:resultArray){

System.out.println(s);

//testB输出

publicstaticvoidtestC(){

Stringstr="abcd";

String[]resultArray=StringUtils.split(str,"ac");

for(Strings:resultArray){

System.out.println(s);

//testC输出

输出结果和预期的一致了。

StringUtils.split源码分析

点开源码一眼看下去,发现在方法注释中就已经进行提示了:返回的字符串数组中不包含分隔符。

TheseparatorisnotincludedinthereturnedStringarray.Adjacentseparatorsaretreatedasoneseparator.FormorecontroloverthesplitusetheStrTokenizerclass....

继续追踪源码,可以看到最终split分割字符串时入参有四个。

privatestaticString[]splitWorker(

finalStringstr,//原字符串

finalStringseparatorChars,//分隔符

finalintmax,//分割后返回前多少个结果,-1为所有

finalbooleanpreserveAllTokens//暂不关注

根据分隔符的不同又分了三种情况。

1.分隔符为null

finalintlen=str.length();

if(len==0){

returnArrayUtils.EMPTY_STRING_ARRAY;

finalListStringlist=newArrayList();

intsizePlus1=1;

inti=0;

intstart=0;

booleanmatch=false;

booleanlastMatch=false;

if(separatorChars==null){

//Nullseparatormeansusewhitespace

while(ilen){

if(Character.isWhitespace(str.charAt(i))){

if(match||preserveAllTokens){

lastMatch=true;

if(sizePlus1++==max){

i=len;

lastMatch=false;

list.add(str.substring(start,i));

match=false;

start=++i;

continue;

lastMatch=false;

match=true;

i++;

//...

if(match||preserveAllTokenslastMatch){

list.add(str.substring(start,i));

可以看到如果分隔符为null,是按照空白字符Character.isWhitespace()分割字符串的。分割的算法逻辑为:

a.用于截取的开始下标置为0,逐字符读取字符串。

b.碰到分割的目标字符,把截取的开始下标到当前字符之前的字符串截取出来。

c.然后用于截取的开始下标置为下一个字符,等到下一次使用。

d.继续逐字符读取字符串、

2.分隔符为单个字符

逻辑同上,只是判断逻辑Character.isWhitespace()变为了指定字符判断。

//Optimise1charactercase

finalcharsep=separatorChars.charAt(0);

while(ilen){

if(str.charAt(i)==sep){//直接比较

3.分隔符为字符串

总计逻辑同上,只是判断逻辑变为包含判断。

//standardcase

while(ilen){

if(separatorChars.indexOf(str.charAt(i))=0){//包含判断

if(match||preserveAllTokens){

如何解决?

1.使用splitByWholeSeparator方法。

我们想要的是按整个字符串分割,StringUtils工具类中已经存在具体的实现了,使用splitByWholeSeparator方法。

Stringstr="aabbccdd";

String[]resultArray=StringUtils.splitByWholeSeparator(str,"bc");

for(Strings:resultArray){

System.out.println(s);

//输出

2.使用GoogleGuava工具库

关于Guava工具库的使用,之前也写过一篇文章,可以参考:Guava-拯救垃圾代码

Stringstr="aabbccdd";

IterableStringiterable=Splitter.on("bc")

.omitEmptyStrings()//忽略空值

.trimResults()//过滤结果中的空白

.split(str);

iterable.forEach(System.out::println);

//输出

3.JDKString.split方法

使用String中的split方法可以实现想要效果。

Stringstr="aabbccdd";

String[]res=str.split("bc");

for(Stringre:res){

System.out.println(re);

//输出

但是String的split方法也有一些坑,比如下面的输出结果。

Stringstr=",a,,b,";

String[]splitArr=str.spli

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论